home *** CD-ROM | disk | FTP | other *** search
- /*
- * netHppi.c --
- *
- * Routines for handling the TMC 29K cards.
- *
- * Copyright 1992 Regents of the University of California
- * Permission to use, copy, modify, and distribute this
- * software and its documentation for any purpose and without
- * fee is hereby granted, provided that the above copyright
- * notice appear in all copies. The University of California
- * makes no representations about the suitability of this
- * software for any purpose. It is provided "as is" without
- * express or implied warranty.
- */
-
- #ifndef lint
- static char rcsid[] = "$Header: /cdrom/src/kernel/Cvsroot/kernel/net/sun4.md/netHppi.c,v 1.4 92/10/26 12:17:41 elm Exp $ SPRITE (Berkeley)";
- #endif /* not lint */
-
- #include <sprite.h>
- #include <vm.h>
- #include <vmMach.h>
- #include <mach.h>
- #include <netUltraInt.h>
- #include <dev/ultra.h>
- #include <netHppi.h>
- #include <netHppiInt.h>
- #include <dev/hppi.h>
- #include <fmt.h>
- #include <sync.h>
- #include <dbg.h>
- #include <rpcPacket.h>
- #include <assert.h>
- #include <list.h>
-
- /*
- * "Borrow" the Vax format for the format of the Ultranet adapter (it
- * is really a 386. We need to swap some of the words in the
- * diagnostic and information structures.
- */
-
- #define NET_ULTRA_FORMAT FMT_VAX_FORMAT
-
- /*
- * The transmit and receive queues are in the dual port RAM on the
- * link board.
- */
- #define QUEUES_IN_DUALPORT_RAM
-
- Boolean netHppiDebug = FALSE;
- Boolean netHppiTrace = FALSE;
- int netHppiMapThreshold = NET_ULTRA_MAP_THRESHOLD;
- static unsigned char netHppiConnPar[] = {0xc6, 0x10, 0x0c, 0x00,
- 0xff, 0xff, 0xff, 0xff,
- 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00};
- static int numHppiInterfaces = 0;
- static NetHppiState* hppiState[NET_HPPI_MAX_INTERFACES];
- static int packetsSunk = 0;
- static Time sinkStartTime;
- static Time sinkEndTime;
-
- #define MIN(a,b) ((a) < (b) ? (a) : (b))
-
- #define WAIT_FOR_REPLY(ptr, count) { \
- int i; \
- for(i = (count); i > 0; i -= 100) { \
- MACH_DELAY(100); \
- if (*((volatile int *)ptr) != 0) { \
- break; \
- } \
- } \
- }
-
- #define WAIT_FOR_BIT_CLEAR(ptr, count, mask) { \
- int i; \
- for (i = (count); i > 0; i -= 100) { \
- if ((*((volatile int *)ptr) & (mask)) == 0) { \
- break; \
- } \
- MACH_DELAY (100); \
- } \
- }
-
-
- /*
- * This is a "wildcard" address that matches any TL address.
- * Once again we have to lie about the size of a Net_Address
- * since the adapter will puke if it isn't 7 bytes (why have it
- * if you can't change it?).
- */
- static Net_UltraTLAddress wildcardAddress =
- {7, NET_ULTRA_TSAP_SIZE};
-
- /*
- * Forward declarations.
- */
-
- static char *GetStatusString _ARGS_ ((int status));
- static Sync_Condition dsndTestDone;
- static Sync_Condition drcvTestDone;
- static Sync_Condition iopOutputDone;
- static int dsndCount;
-
- static void InitQueues _ARGS_((NetHppiState *statePtr));
- static void StandardDone _ARGS_((Net_Interface *interPtr,
- NetUltraXRBInfo *infoPtr));
- static ReturnStatus NetHppiSendDgram _ARGS_((Net_Interface *interPtr,
- Net_Address *netAddressPtr, int count,
- int bufSize, Address buffer, Time *timePtr));
- static void DgramSendDone _ARGS_((Dev_HppiSendDSND* dgramCmdPtr));
- static void NetHppiRecvDgram _ARGS_((Net_Interface *interPtr));
- static void DgramRecvDone _ARGS_((Dev_HppiSendDRCV* dgramCmdPtr));
- static void SourceDone _ARGS_((Net_Interface *interPtr,
- NetUltraXRBInfo *infoPtr));
- static ReturnStatus NetHppiSource _ARGS_((Net_Interface *interPtr,
- Net_Address *netAddressPtr, int count,
- int bufSize, Address buffer, Time *timePtr));
- static void NetHppiResetCallback _ARGS_((ClientData data,
- Proc_CallInfo *infoPtr));
- static void NetHppiMsgCallback _ARGS_((ClientData data,
- Proc_CallInfo *infoPtr));
- static void NetHppiCmdCallback _ARGS_((ClientData data,
- Proc_CallInfo *infoPtr));
- static ReturnStatus NetHppiSetupBoard _ARGS_((NetHppiState *interPtr));
- static ReturnStatus NetHppiStart _ARGS_((NetHppiState *statePtr));
- static ReturnStatus NetHppiStop _ARGS_((NetHppiState *statePtr));
- static ReturnStatus NetHppiSendReq _ARGS_((NetHppiState *statePtr,
- void (*doneProc)(), ClientData data,
- Boolean rpc, int scatterLength,
- Net_ScatterGather *scatterPtr,
- int requestSize, NetUltraRequest *requestPtr));
- static ReturnStatus NetHppiSendCmd _ARGS_((NetHppiState *statePtr,
- int size, Address cmdPtr,
- int flags));
- static void NetHppiConnectionAccepted _ARGS_((Dev_HppiSendALSN*
- connBlockPtr));
- static void NetHppiXferCallback _ARGS_((Dev_HppiSendXfer* cmdPtr));
- static void NetHppiOpenCallback _ARGS_((Dev_HppiSendOPEN* cmdPtr));
- static void NetHppiConnectionCleanup _ARGS_((Dev_HppiSendRLSE*
- cmdPtr));
- static NetHppiOutputStub _ARGS_((Net_Interface* interPtr, Address hdrPtr,
- Net_ScatterGather* scatterGatherPtr,
- int scatterGatherLength, Boolean rpc,
- ReturnStatus* statusPtr));
- static void iocConnCallback _ARGS_ ((Net_HppiConnection* connPtr));
- static void iocXferCallback _ARGS_ ((Net_HppiDataRequest* dataReqPtr));
- /*
- * Macros for mapping between kernel, DVMA and VME addresses.
- */
-
- #define DVMA_TO_BUFFER(addr, statePtr) \
- ((Address) (((((unsigned int) (addr)) - \
- ((unsigned int) (statePtr)->buffersDVMA)) + \
- ((int) (statePtr)->buffers))))
-
- #define BUFFER_TO_DVMA(addr, statePtr) \
- ((Address) ((((unsigned int) (addr)) - \
- ((unsigned int) (statePtr)->buffers)) + \
- ((unsigned int) (statePtr)->buffersDVMA)))
-
- #define DVMA_TO_VME(addr, statePtr) \
- ((Address) (((unsigned int) (addr)) - \
- ((unsigned int) VMMACH_DMA_START_ADDR)))
-
- #define VME_TO_DVMA(addr, statePtr) \
- ((Address) ((((unsigned int)(addr)) & 0x00ffffff) + \
- ((unsigned int) VMMACH_DMA_START_ADDR)))
-
- #define BUFFER_TO_VME(addr, statePtr) \
- ((Address) (DVMA_TO_VME(BUFFER_TO_DVMA(addr,statePtr), (statePtr))))
-
- #define VME_TO_BUFFER(addr, statePtr) \
- ((Address) (DVMA_TO_BUFFER(VME_TO_DVMA((addr),statePtr),(statePtr))))
-
- #define DVMA_ADDRESS(addr, statePtr) \
- ((unsigned int)(addr) < ((unsigned int)VMMACH_DMA_START_ADDR)? FALSE :TRUE)
-
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiInit --
- *
- * Initialize the TMC VME boards.
- *
- * Results:
- * SUCCESS if the TMC cards were found and initialized.
- * FAILURE otherwise.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- NetHppiInit(interPtr)
- Net_Interface *interPtr; /* Network interface. */
- {
- unsigned int ctrlAddr;
- ReturnStatus status = SUCCESS;
- NetHppiState *statePtr;
- unsigned long initialTsap = 0x07d00000;
-
- /*
- * First, see if the controller is present. We will *always* map it
- * in, since we need to map in two different controllers--the HPPI-S
- * and HPPI-D have different addresses. The controller address
- * specified will be the setting of bits 23:16 on the boards (see
- * their documentation for specifics)
- */
- ctrlAddr = (unsigned int) interPtr->ctrlAddr;
-
- printf ("NetHppiInit: Trying to locate HPPI boards at VME24D32 0x%x.\n",
- ctrlAddr);
- if (numHppiInterfaces == 0) {
- int i;
- for (i = 0; i < NET_HPPI_MAX_INTERFACES; i++) {
- hppiState[i] = NULL;
- }
- } else if (numHppiInterfaces > NET_HPPI_MAX_INTERFACES) {
- printf ("NetHppiInit: too many HPPI interfaces\n");
- status = FAILURE;
- goto initFailed;
- }
- statePtr = (NetHppiState *)malloc (sizeof (NetHppiState));
-
- if (statePtr == NULL) {
- panic ("NetHppiInit: unable to allocate state area\n");
- }
- hppiState[numHppiInterfaces] = statePtr;
-
- /*
- * Map in boards and attempt to reset them. If the reset fails, then
- * the boards probably aren't actually there. NOTE: the last
- * parameter to VmMach_MapInDevice is the address space. 3 corresponds
- * to VME A24D32.
- */
- statePtr->hppisReg = (NetHppiSrcReg *)
- VmMach_MapInDevice((Address) (ctrlAddr + NET_HPPI_SRC_CTRL_OFFSET), 3);
- statePtr->hppidReg = (NetHppiDestReg *)
- VmMach_MapInDevice((Address) (ctrlAddr + NET_HPPI_DST_CTRL_OFFSET), 3);
- statePtr->iopReg = (NetHppiIopReg *)
- VmMach_MapInDevice((Address) (ctrlAddr + NET_HPPI_IOP_CTRL_OFFSET), 3);
-
- if ((statePtr->hppidReg == NULL) || (statePtr->hppisReg == NULL)) {
- printf ("NetHppiInit: Unable to get map space for boards.\n");
- status = FAILURE;
- goto initFailed;
- } else {
- printf ("NetHppiInit: SRC at virtual 0x%x; DST at virtual 0x%x \n",
- statePtr->hppisReg, statePtr->hppidReg);
- }
-
- /*
- * Reset both boards...
- */
- statePtr->magic = NET_HPPI_STATE_MAGIC;
- statePtr->interPtr = interPtr;
- interPtr->interfaceData = (ClientData) statePtr;
- statePtr->tracePtr = statePtr->traceBuffer;
- statePtr->traceSequence = 0;
- statePtr->queuesInit = FALSE;
- statePtr->priority = NET_HPPI_INTERRUPT_PRIORITY;
- statePtr->requestLevel = NET_HPPI_VME_REQUEST_LEVEL;
- statePtr->addressSpace = NET_HPPI_VME_ADDRESS_SPACE;
- statePtr->hppiNum = numHppiInterfaces;
- statePtr->boardFlags = 0;
- bcopy (&initialTsap, statePtr->curTsap, sizeof (statePtr->curTsap));
- Mach_SetHandler (interPtr->vector, Net_Intr, (ClientData) interPtr);
- interPtr->init = NetHppiInit;
- interPtr->intr = NetHppiIntr;
- interPtr->ioctl = NetHppiIOControl;
- interPtr->reset = Net_HppiReset;
- interPtr->output = NetHppiOutputStub;
- interPtr->netType = NET_NETWORK_ULTRA;
- interPtr->maxBytes = NET_HPPI_MAX_BYTES;
- interPtr->minBytes = NET_HPPI_MIN_BYTES;
- interPtr->ctrlAddr = (Address) ctrlAddr;
- status = NetHppiHardReset (interPtr);
- if (status != SUCCESS) {
- printf ("NetHppiInit: board reset failed (boards not present?)\n");
- goto initFailed;
- }
- #if 0
- status = NetHppiInfo (statePtr);
- if (status == SUCCESS) {
- printf ("Hppi boards successfully got info.\n");
- } else {
- printf ("NetHppiInit: unable to get info from board.\n");
- status = FAILURE;
- goto initFailed;
- }
- #endif
-
-
- initFailed:
- numHppiInterfaces += 1;
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiHardReset --
- *
- * Does a hard reset of the Ultranet adapter. This means the adapter
- * board goes back to its state right after power-up -- no
- * micro-code or anything.
- *
- * Results:
- * SUCCESS if a reply was received properly, FAILURE otherwise
- *
- * Side effects:
- * The ultranet adapter is initialized.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- NetHppiHardReset(interPtr)
- Net_Interface *interPtr; /* Interface to reset. */
- {
- NetHppiState *statePtr; /* State of the adapter. */
- ReturnStatus status = SUCCESS;
- int resetVal;
- int srcStatus = SUCCESS, dstStatus = SUCCESS;
-
- if (netHppiDebug) {
- printf ("NetHppiHardReset: entering....\n");
- }
- resetVal = NET_HPPI_RESET_BOARD | NET_HPPI_RESET_CPU;
- statePtr = (NetHppiState *) interPtr->interfaceData;
- printf("Hppi: hard reset boards.\n");
-
- srcStatus = Mach_Probe(sizeof(int), (char *) &resetVal,
- (char *) &(statePtr->hppisReg->reset));
-
- dstStatus = Mach_Probe(sizeof(int), (char *) &resetVal,
- (char *) &(statePtr->hppidReg->reset));
-
- if (srcStatus != SUCCESS) {
- /*
- * Board is no longer responding.
- */
- printf("NetHppiHardReset: HPPI-S did not respond to reset!! 0x%x\n",
- srcStatus);
- statePtr->flags = 0;
- status = FAILURE;
- }
-
- if (dstStatus != SUCCESS) {
- /*
- * Board is no longer responding.
- */
- printf("NetHppiHardReset: HPPI-D did not respond to reset!! 0x%x\n",
- dstStatus);
- statePtr->flags = 0;
- status = FAILURE;
- }
-
- if (status != SUCCESS) {
- return status;
- }
-
- MACH_DELAY(NET_HPPI_RESET_DELAY);
-
- statePtr->hppisReg->reset = 0;
- statePtr->hppidReg->reset = 0;
- statePtr->hppisReg->config = NET_HPPI_SRC_CONFIG_VALUE;
- statePtr->hppidReg->config = NET_HPPI_DST_CONFIG_VALUE;
- statePtr->outputCallback = NULL;
- InitQueues(statePtr);
- /*
- * After a reset the adapter is in the EPROM mode.
- * This allows several additional commands (load, go, etc.) to be
- * sent to the adapter.
- */
- statePtr->flags = (NET_HPPI_STATE_EXIST | NET_HPPI_STATE_SRC_EPROM |
- NET_HPPI_STATE_DST_EPROM);
-
- if (netHppiDebug) {
- printf ("NetHppiHardReset: exiting....\n");
- }
-
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiReset --
- *
- * Resets the board by sending it a stop command followed by a
- * start command. The XRB queues are also initialized.
- * Assumes the interface mutex is held.
- *
- * Results:
- * A standard Sprite return status.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- NetHppiReset(interPtr)
- Net_Interface *interPtr; /* Interface to reset. */
- {
- ReturnStatus status = SUCCESS;
- NetHppiState *statePtr; /* State of the adapter. */
- Dev_HppiReset resetCmd; /* reset command for both src & dst */
- int which = 0; /* reset SRC, DST, or both */
-
- statePtr = (NetHppiState *) interPtr->interfaceData;
- if (which == 0) {
- which = NET_HPPI_SRC_CMD | NET_HPPI_DST_CMD;
- }
- if (netHppiDebug) {
- if (which & NET_HPPI_SRC_CMD) {
- printf ("NetHppiReset: resetting SRC board.\n");
- }
- if (which & NET_HPPI_DST_CMD) {
- printf ("NetHppiReset: resetting DST board.\n");
- }
- }
-
- resetCmd.hdr.opcode = DEV_HPPI_RESET;
- if (which & NET_HPPI_SRC_CMD) {
- resetCmd.hdr.magic = DEV_HPPI_SRC_MAGIC;
- status = NetHppiSendCmd (statePtr, sizeof (resetCmd),
- (Address)&resetCmd, NET_HPPI_SRC_CMD);
- if (status != SUCCESS) {
- printf ("NetHppiReset: soft reset of SRC board failed.\n");
- return (status);
- }
- }
-
- if (which & NET_HPPI_DST_CMD) {
- resetCmd.hdr.magic = DEV_HPPI_DEST_MAGIC;
- status = NetHppiSendCmd (statePtr, sizeof (resetCmd),
- (Address)&resetCmd, 0);
- if (status != SUCCESS) {
- printf ("NetHppiReset: soft reset of DST board failed.\n");
- }
- }
-
- InitQueues(statePtr);
-
- statePtr->flags = NET_HPPI_STATE_EXIST;
-
- if (which & NET_HPPI_RESET_RESTART) {
- status = NetHppiSetupBoard (statePtr);
-
- status = NetHppiStop(statePtr);
- if (status != NULL) {
- printf("NetHppiReset: stop failed\n");
- return status;
- }
-
- status = NetHppiStart(statePtr);
- if (status != NULL) {
- printf("NetHppiReset: start failed\n");
- return status;
- }
- }
- if (netHppiDebug) {
- printf ("NetHppiReset: reset done...returning.\n");
- }
-
- return (status);
- }
-
- /*----------------------------------------------------------------------
- *
- * Net_HppiReset --
- *
- * Reset the HPPI boards. This can be called
- * from outside the module since it locks the mutex.
- *
- * Results:
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Net_HppiReset(interPtr)
- Net_Interface *interPtr; /* Interface to reset. */
- {
- MASTER_LOCK(&interPtr->mutex);
- /*
- * If we are at interrupt level we have to do a callback to reset
- * the adapter since we can't wait for the response from
- * the adapter (there may not be a current process and we can't
- * get the interrupt).
- */
- if (Mach_AtInterruptLevel()) {
- Proc_CallFunc(NetHppiResetCallback, (ClientData) interPtr, 0);
- } else {
- (void) NetHppiReset(interPtr);
- }
- MASTER_UNLOCK(&interPtr->mutex);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiResetCallback --
- *
- * This routine is called by the Proc_ServerProc during the
- * callback to reset the adapter.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The adapter is reset.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- NetHppiResetCallback(data, infoPtr)
- ClientData data; /* Ptr to the interface to reset. */
- Proc_CallInfo *infoPtr; /* Unused. */
- {
- Net_HppiReset((Net_Interface *) data);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * Net_HppiHardReset --
- *
- * This is a version of the hard reset routine that can be called from
- * outside the net module because it does not assume that a
- * lock is held (or interrupts are disabled) when it is called.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The adapter is reset.
- *
- *----------------------------------------------------------------------
- */
-
- void
- Net_HppiHardReset(interPtr)
- Net_Interface *interPtr; /* Interface to reset. */
- {
- MASTER_LOCK(&interPtr->mutex);
-
- NetHppiHardReset(interPtr);
-
- MASTER_UNLOCK(&interPtr->mutex);
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * getSgTag --
- *
- * Get a free tag for the scatter-gather array. This assumes that
- * the mutex is held by the calling routine.
- *
- * Results:
- * The tag to use (or -1 if none available).
- * Side effects:
- * A tag is allocated.
- *
- *----------------------------------------------------------------------
- */
- static
- int
- getSgTag (statePtr)
- NetHppiState* statePtr;
- {
- int i;
- int curTag;
-
- for (i = 0, curTag = statePtr->curSgTag; statePtr->tags[curTag] != 0;
- curTag ++, i++) {
- if (curTag == NET_HPPI_MAX_TAGS) {
- curTag = 1;
- }
- if (i == NET_HPPI_MAX_TAGS - 1) {
- printf ("getSgTag: no free tags!\n");
- return (-1);
- }
- }
- statePtr->curSgTag = curTag;
- statePtr->tags[curTag] = 1;
-
- return (curTag);
- }
-
- static
- void
- freeSgTag (statePtr, tag)
- NetHppiState* statePtr;
- char tag;
- {
- if (netHppiDebug) {
- printf ("freeing hppi tag %d\n", tag);
- }
- statePtr->tags[tag] = 0;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiCopyFromFifo --
- *
- * Copy a command to the appropriate FIFO (its address is passed).
- * This is similar to bcopy, except all the words in the source
- * address are copied to the (single) address corresponding to
- * a HPPI board FIFO.
- *
- * Results:
- * SUCCESS if the adapter responded to the command,
- * DEV_TIMEOUT if the adapter did not respond
- *
- * Side effects:
- * The data is copied to the appropriate FIFO.
- *
- *----------------------------------------------------------------------
- */
- static
- ReturnStatus
- NetHppiCopyFromFifo (addr, size, statePtr, which)
- uint32 *addr; /* the command to be sent */
- int size; /* size of the command (in bytes) */
- NetHppiState *statePtr;
- int which; /* copy from SRC or dst fifo? */
- {
- volatile uint32 *fifoAddr; /* address of the FIFO to copy to */
- volatile uint32 *stateAddr; /* address of state register */
- register uint32 *kaddr = addr;
- ReturnStatus status = SUCCESS;
- int i;
-
- if (which == NET_HPPI_SRC_CMD) {
- stateAddr = &(statePtr->hppisReg->status);
- fifoAddr = &(statePtr->hppisReg->outputFifo);
- } else {
- stateAddr = &(statePtr->hppidReg->status);
- fifoAddr = &(statePtr->hppidReg->outputFifo);
- }
-
- if (netHppiDebug) {
- printf ("NetHppiCopyFromFifo: trying to copy %d bytes from fifo.\n",
- size);
- }
- for (i = 0; i < size; i += 4) {
- WAIT_FOR_BIT_CLEAR (stateAddr, NET_HPPI_DELAY, DEV_HPPI_OFIFO_EMPTY);
- if ((*stateAddr) & DEV_HPPI_OFIFO_EMPTY) {
- if (netHppiDebug) {
- printf ("\nNetHppiCopyFromFifo: copy timed out.\n");
- }
- return (DEV_TIMEOUT);
- }
- *addr = *fifoAddr;
- if (netHppiDebug) {
- printf ("0x%08x ", *addr);
- if ((i % 32) == 31) {
- printf ("\n");
- }
- }
- addr++;
- }
-
- if (netHppiDebug) {
- printf ("\nNetHppiCopyFromFifo: copied %d bytes from fifo to 0x%x\n",
- size, kaddr);
- }
- return (status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiCopyToFifo --
- *
- * Copy a command to the appropriate FIFO (its address is passed).
- * This is similar to bcopy, except all the words in the source
- * address are copied to the (single) address corresponding to
- * a HPPI board FIFO.
- *
- * Results:
- * SUCCESS if the adapter responded to the command,
- * DEV_TIMEOUT if the adapter did not respond
- *
- * Side effects:
- * The data is copied to the appropriate FIFO.
- *
- *----------------------------------------------------------------------
- */
- static
- ReturnStatus
- NetHppiCopyToFifo (addr, size, statePtr, which)
- uint32 *addr; /* the command to be sent */
- int size; /* size of the command (in bytes) */
- NetHppiState *statePtr; /* ptr to HPPI state */
- int which; /* copy to src or dest fifo? */
- {
- volatile uint32 *fifoAddr; /* address of the FIFO to copy to */
- volatile uint32 *stateAddr; /* address of state register */
- register uint32 *kaddr = addr;
- register int cnt, xferCnt, i;
- ReturnStatus status = SUCCESS;
-
- if (which == NET_HPPI_SRC_CMD) {
- stateAddr = &(statePtr->hppisReg->status);
- fifoAddr = &(statePtr->hppisReg->inputFifo);
- } else {
- stateAddr = &(statePtr->hppidReg->status);
- fifoAddr = &(statePtr->hppidReg->inputFifo);
- }
-
- cnt = size;
- while (cnt > 0) {
- xferCnt = (cnt > (DEV_HPPI_IFIFO_DEPTH/2 - 16)) ?
- (DEV_HPPI_IFIFO_DEPTH/2 - 16) : cnt;
- for (i = 0; i < xferCnt; i += 4, cnt -= 4) {
- *fifoAddr = *(addr++);
- }
- if (cnt > 0) {
- WAIT_FOR_BIT_CLEAR (stateAddr, NET_HPPI_DELAY, DEV_HPPI_IFIFO_HF);
- if ((*stateAddr) & DEV_HPPI_IFIFO_HF) {
- #ifndef CLEAN
- if (netHppiDebug) {
- printf ("NetHppiCopyToFifo: timeout after %d bytes\n",
- size - i);
- }
- #endif
- return (DEV_TIMEOUT);
- }
- }
- }
-
- if (netHppiDebug) {
- printf ("NetHppiCopyToFifo: copied %d bytes from 0x%x to fifo\n",
- size, kaddr);
- }
- return (status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiReleaseSrcFifo
- *
- * Release the HPPI-S command FIFO. It must have been previously
- * acquired by NetHppiAcquireSrcFifo.
- *
- * Results:
- * SUCCESS if the adapter responded to the command,
- *
- * Side effects:
- * The server releases control of the HPPI-S command FIFO.
- *
- *----------------------------------------------------------------------
- */
- static
- ReturnStatus
- NetHppiReleaseSrcFifo (statePtr)
- NetHppiState *statePtr; /* state of the adapter */
- {
- ReturnStatus status = SUCCESS;
-
- if (!(statePtr->flags & NET_HPPI_OWN_SRC_FIFO)) {
- printf ("NetHppiReleaseSrcFifo: don't own SRC FIFO.\n");
- }
-
- #if 0
- statePtr->hppidReg->commandData = 0x0;
- statePtr->flags &= ~NET_HPPI_OWN_SRC_FIFO;
- #endif
-
- return (status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiAcquireSrcFifo
- *
- * Arbitrate with the HPPI-D board to get access to the HPPI-S
- * FIFO. This is done so the HPPI-D and the server don't
- * interleave requests in the HPPI-S command FIFO.
- *
- * Results:
- * SUCCESS if the adapter responded to the command,
- * DEV_TIMEOUT if the adapter did not respond within a specified time.
- *
- * Side effects:
- * The server gets control of the HPPI-S command FIFO.
- *
- *----------------------------------------------------------------------
- */
- static
- ReturnStatus
- NetHppiAcquireSrcFifo (statePtr, timeOutVal)
- NetHppiState *statePtr; /* state of the adapter */
- int timeOutVal; /* maximum time to wait */
- {
- ReturnStatus status = SUCCESS;
- #if 0
- volatile NetHppiDestReg *destReg = statePtr->hppidReg;
- #endif
-
- #if 0
- /*
- * Notify the HPPI-D that we want to talk to the HPPI-S.
- */
- destReg->commandData = 0x10000;
- destReg->command |= 0x1000000;
-
- /*
- * Wait for the HPPI-D to grant our request;
- */
- while (!((destReg->responseData == 0x0) &&
- (!(destReg->command & 0xff000000)) &&
- (timeOutVal > 0)) {
- timeOutVal -= 1;
- }
- #endif
-
- statePtr->flags |= NET_HPPI_OWN_SRC_FIFO;
-
- if (timeOutVal == 0) {
- status = NetHppiReleaseSrcFifo (statePtr);
- if (status != SUCCESS) {
- panic ("NetHppiAcquireSrcFifo: timeout and FIFO release failed.\n");
- }
- status = DEV_TIMEOUT;
- }
-
- return (status);
- }
-
- /*------------------------------------------------------------
- *
- * getFreeBuffer
- *
- * This routine removes a buffer from the list of free buffers.
- *
- *------------------------------------------------------------
- */
- static
- Address
- getFreeBuffer (statePtr)
- NetHppiState *statePtr;
- {
- List_Links *itemPtr;
- int signal;
-
- while(List_IsEmpty(statePtr->freeBufferList)) {
- statePtr->bufferAvail.waiting = TRUE;
- signal = Sync_SlowMasterWait((unsigned int) &statePtr->bufferAvail,
- &(statePtr->interPtr->mutex), TRUE);
- if (signal) {
- return ((Address)NIL);
- }
- }
- itemPtr = List_First(statePtr->freeBufferList);
- if (itemPtr == statePtr->freeBufferList) {
- panic("NetHppi: getFreeBuffer list screwup\n");
- }
- List_Remove(itemPtr);
-
- return ((Address)itemPtr);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiSendCmd --
- *
- * Send a command to the adapter.
- *
- * Results:
- * SUCCESS if the adapter responded to the command,
- * DEV_TIMEOUT if the adapter did not respond
- *
- * Side effects:
- * A command is sent to the adapter.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- NetHppiSendCmd(statePtr, size, cmdPtr, flags)
- NetHppiState *statePtr; /* State of the adapter. */
- int size; /* Size of command block. */
- Address cmdPtr; /* The command block. */
- int flags; /* flags pertaining to this command */
- {
- ReturnStatus status = SUCCESS;
- Dev_HppiCmdHdr *cmdHdr = (Dev_HppiCmdHdr *)cmdPtr;
-
- /*
- * We must copy the command to the adapter ourselves, so there's
- * no point in mapping the command into DMA memory. If the command
- * goes to the destination, we just copy the command into the
- * destination's FIFO. If it goes into the source, we must
- * arbitrate for control of the FIFO. We can't wait for results
- * since incoming packet information could arrive first.
- */
- if (netHppiDebug) {
- printf("NetHppiSendCmd: sending command %d to adapter\n",
- cmdHdr->opcode);
- printf("NetHppiSendCmd: size = %d, cmdPtr = 0x%x\n", size, cmdPtr);
- }
- if ((int) cmdPtr & 0x3) {
- panic("NetHppiSendCmd: command not aligned on a word boundary\n");
- }
-
- if (flags & NET_HPPI_SRC_CMD) {
- if (flags & NET_HPPI_STATE_SRC_EPROM) {
- printf ("NetHppiSendCmd: SRC not running\n");
- status = FAILURE;
- goto exit;
- }
- cmdHdr->magic = DEV_HPPI_SRC_MAGIC;
- if (!(statePtr->flags & NET_HPPI_OWN_SRC_FIFO)) {
- status = NetHppiAcquireSrcFifo (statePtr, 1000000);
- }
- if (status == SUCCESS) {
- status = NetHppiCopyToFifo (cmdPtr, size, statePtr,
- NET_HPPI_SRC_CMD);
- }
- if (!(flags & NET_HPPI_KEEP_SRC_FIFO)) {
- NetHppiReleaseSrcFifo (statePtr);
- }
- } else {
- if (flags & NET_HPPI_STATE_DST_EPROM) {
- printf ("NetHppiSendCmd: DST not running\n");
- status = FAILURE;
- goto exit;
- }
- cmdHdr->magic = DEV_HPPI_DEST_MAGIC;
- status = NetHppiCopyToFifo (cmdPtr, size, statePtr, 0);
- }
-
- if (netHppiDebug) {
- printf ("NetHppiSendCmd: command sent (status = %d).\n", status);
- }
-
- exit:
- return (status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiMsgCallback
- *
- * This is the routine called back by a ServerProc to handle a
- * message from the HPPI boards. The message can be one of three
- * types: an error message from either HPPI-S or HPPI-D, or a
- * request from the HPPI-D to send data to the HPPI-S.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The message is retrieved from the HPPI board(s) and appropriate
- * actions are taken.
- *
- *----------------------------------------------------------------------
- */
- static
- void
- NetHppiMsgCallback (data, infoPtr)
- ClientData data;
- Proc_CallInfo *infoPtr;
- {
- Net_Interface *interPtr = (Net_Interface *)data;
- NetHppiState *statePtr = (NetHppiState *)interPtr->interfaceData;
- Dev_HppiErrorMsg errMsg;
- int size;
- int numElements;
- int i;
- int status = SUCCESS;
-
- if (netHppiDebug) {
- printf ("NetHppiMsgCallback: entering with data = 0x%x\n", data);
- }
- if (!(statePtr->flags &
- (NET_HPPI_STATE_SRC_ERROR | NET_HPPI_STATE_DST_ERROR))) {
- Dev_HppiCopyDataMsg copyDataMsg;
- Dev_HppiOutput outputCmd;
-
- size = sizeof (copyDataMsg.size) + sizeof (copyDataMsg.magic) +
- sizeof (copyDataMsg.dmaWord);
-
- /*
- * Copy the entire message from the destination board. Since
- * we can only get one type of message, we don't need to check
- * message type except for verification.
- */
- NetHppiCopyFromFifo (©DataMsg, size, statePtr, 0);
- if (copyDataMsg.magic != DEV_HPPI_COPY_MAGIC) {
- printf ("NetHppiMsgCallback: bad copyToSource magic number\n");
- goto exit;
- }
- NetHppiCopyFromFifo (&(copyDataMsg.element[0]), copyDataMsg.size,
- statePtr, 0);
- if (netHppiTrace) {
- outputCmd.hdr.opcode = DEV_HPPI_OUTPUT_TRACE;
- } else {
- outputCmd.hdr.opcode = DEV_HPPI_OUTPUT;
- }
-
- numElements = copyDataMsg.size / sizeof (copyDataMsg.element[0]);
- for (i = 0, size = sizeof (copyDataMsg.dmaWord);
- i < numElements; i++) {
- size += copyDataMsg.element[i].size;
- }
- copyDataMsg.dmaWord.cmd &= ~NET_ULTRA_DMA_CMD_FROM_ADAPTER;
- copyDataMsg.dmaWord.cmd |= NET_ULTRA_DMA_CMD_DMA_DATA;
- outputCmd.hdr.magic = DEV_HPPI_SRC_MAGIC;
- outputCmd.fifoDataSize = size;
- outputCmd.iopDataSize = 0;
- NetHppiSendCmd (statePtr, sizeof (outputCmd), (Address)&outputCmd,
- NET_HPPI_SRC_CMD | NET_HPPI_KEEP_SRC_FIFO);
- NetHppiCopyToFifo (&(copyDataMsg.dmaWord),
- sizeof (copyDataMsg.dmaWord), statePtr,
- NET_HPPI_SRC_CMD);
- /*
- * Copy scatter-gather buffers to input FIFO.
- */
- for (i = 0; i < numElements; i++) {
- NetHppiCopyToFifo (VME_TO_BUFFER (copyDataMsg.element[i].address,
- statePtr),
- copyDataMsg.element[i].size, statePtr,
- NET_HPPI_SRC_CMD);
- }
- NetHppiReleaseSrcFifo (statePtr);
- } else {
- if (statePtr->flags & NET_HPPI_STATE_SRC_ERROR) {
- status = NetHppiCopyFromFifo (&errMsg, sizeof (errMsg),
- statePtr, NET_HPPI_SRC_CMD);
- if (errMsg.magic != DEV_HPPI_ERR_MAGIC) {
- printf ("NetHppiMsgCallback: bad SRC error magic number\n");
- goto exit;
- }
- if (netHppiDebug) {
- printf ("NetHppiMsgCallback: SRC error (%d words)\n",
- errMsg.errorInfoLength);
- }
- status = NetHppiCopyFromFifo (&(statePtr->srcErrorBuffer),
- (errMsg.errorInfoLength << 2),
- statePtr, NET_HPPI_SRC_CMD);
- }
-
- if (statePtr->flags & NET_HPPI_STATE_DST_ERROR) {
- status = NetHppiCopyFromFifo (&errMsg, sizeof (errMsg), statePtr,
- NET_HPPI_SRC_CMD);
- if (errMsg.magic != DEV_HPPI_ERR_MAGIC) {
- printf ("NetHppiMsgCallback: bad DST error magic number\n");
- goto exit;
- }
- if (netHppiDebug) {
- printf ("NetHppiMsgCallback: DST error (%d words)\n",
- errMsg.errorInfoLength);
- }
- status = NetHppiCopyFromFifo (&(statePtr->dstErrorBuffer),
- (errMsg.errorInfoLength << 2),
- statePtr, 0);
- }
- }
-
- exit:
- if (status != SUCCESS) {
- printf ("NetHppiMsgCallback: error 0x%x occurred\n", status);
- }
- if (netHppiDebug) {
- printf ("NetHppiMsgCallback: returning....\n");
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiLoopback
- *
- * Set up the HIPPI boards for loopback testing. This can either
- * mean a full loopback from xbus to hipppi and back, or a partial
- * loop from SRC -> DST -> XBUS.
- *
- * Returns:
- * none
- * Side effects:
- * Sends commands to the HIPPI boards.
- *
- *----------------------------------------------------------------------
- */
- static
- void
- NetHppiLoopback (statePtr, size, callbackProc, clientData, srcPat)
- NetHppiState* statePtr;
- int size; /* size in BYTES */
- void (*callbackProc)();
- ClientData clientData;
- int srcPat;
- {
- Dev_HppiOutput outputCmd;
- Dev_HppiOutputPattern patternCmd;
-
- if (statePtr->outputCallback != NULL) {
- (callbackProc)(clientData, FAILURE);
- } else {
- statePtr->outputCallback = callbackProc;
- statePtr->outputClientData = clientData;
- outputCmd.fifoDataSize = 0;
- outputCmd.iopDataSize = size;
- outputCmd.hdr.opcode = DEV_HPPI_OUTPUT_TO_IOP;
- NetHppiSendCmd (statePtr, sizeof (outputCmd), (Address)&outputCmd,
- NET_HPPI_DST_CMD);
- if (srcPat == 0) {
- outputCmd.hdr.opcode = DEV_HPPI_OUTPUT;
- NetHppiSendCmd (statePtr, sizeof (outputCmd), (Address)&outputCmd,
- NET_HPPI_SRC_CMD);
- } else if (srcPat == 1) {
- patternCmd.hdr.opcode = DEV_HPPI_OUTPUT_PATTERN;
- patternCmd.size = size;
- patternCmd.start = 0;
- patternCmd.increment = 0x00010001;
- NetHppiSendCmd (statePtr, sizeof (patternCmd),(Address)&patternCmd,
- NET_HPPI_SRC_CMD);
- }
- }
- }
-
- static
- void
- iopOutputCallback (statePtr, status)
- NetHppiState* statePtr;
- ReturnStatus status;
- {
- MASTER_LOCK (&(statePtr->interPtr->mutex));
- if (!(statePtr->flags & NET_HPPI_STATE_IOP_OUTPUT_TEST)) {
- printf ("Hppi iopOutputCallback: not testing iop?\n");
- }
- statePtr->flags &= ~NET_HPPI_STATE_IOP_OUTPUT_TEST;
- Sync_MasterBroadcast (&iopOutputDone);
- MASTER_UNLOCK (&(statePtr->interPtr->mutex));
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Net_HppiLoopback
- *
- * This routine is intended ONLY for debugging. It calls NetHppiLoopback
- * to send data from IOP bus -> HIPPI-S -> HIPPI-D -> IOP bus.
- * The supplied callback routine will be called when the
- * transfer completes. Note that the callback may occur at interrupt
- * level. Also, only one of these transfers may be outstanding at any
- * time. If this is called while there is still an outstanding output
- * command, the callback will immediately be called with FAILURE status.
- *
- * Returns:
- * none
- * Side effects:
- * Commands are sent to the HIPPI-D and HIPPI-S boards.
- *
- *----------------------------------------------------------------------
- */
- void
- Net_HppiLoopback (hippiNum, size, callbackProc, clientData)
- int hippiNum;
- int size; /* size in BYTES */
- void (*callbackProc)();
- ClientData clientData;
- {
- NetHppiState* statePtr;
-
- if (netHppiDebug) {
- printf ("Net_HppiLoopback: called for unit %d.\n", hippiNum);
- }
- if ((hippiNum >= NET_HPPI_MAX_INTERFACES) ||
- (statePtr = hppiState[hippiNum]) == NULL) {
- (callbackProc)(clientData, DEV_INVALID_UNIT);
- return;
- }
- MASTER_LOCK (&(statePtr->interPtr->mutex));
- NetHppiLoopback (statePtr, size, callbackProc, clientData, 0);
- MASTER_UNLOCK (&(statePtr->interPtr->mutex));
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * Net_HppiSrcPattern
- *
- * This routine is almost identical to Net_HppiLoopback, except
- * that the HIPPI source board is set up to provide a fixed
- * pattern rather than use data from the IOP bus.
- *
- * Returns:
- * none
- * Side effects:
- * Sets up HIPPI boards.
- *
- *----------------------------------------------------------------------
- */
- void
- Net_HppiSrcPattern (hippiNum, size, callbackProc, clientData)
- int hippiNum;
- int size; /* size in BYTES */
- void (*callbackProc)();
- ClientData clientData;
- {
- NetHppiState* statePtr;
-
- if (netHppiDebug) {
- printf ("Net_HppiSrcPattern: called for unit %d.\n", hippiNum);
- }
- if ((hippiNum >= NET_HPPI_MAX_INTERFACES) ||
- (statePtr = hppiState[hippiNum]) == NULL) {
- (callbackProc)(clientData, DEV_INVALID_UNIT);
- return;
- }
- MASTER_LOCK (&(statePtr->interPtr->mutex));
- NetHppiLoopback (statePtr, size, callbackProc, clientData, 1);
- MASTER_UNLOCK (&(statePtr->interPtr->mutex));
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiIntr --
- *
- * Handle an interrupt from the HPPI boards.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- /*ARGSUSED*/
- void
- NetHppiIntr(interPtr, polling)
- Net_Interface *interPtr; /* Interface to process. */
- Boolean polling; /* TRUE if are being polled instead of
- * processing an interrupt. */
- {
- NetUltraXRB *xrbPtr;
- NetUltraXRB *nextXRBPtr;
- NetHppiState *statePtr;
- volatile NetUltraDMAInfo *dmaPtr;
- NetUltraRequestHdr *hdrPtr;
- NetUltraXRBInfo *infoPtr;
- int processed;
- NetUltraTraceInfo *tracePtr;
- Address buffer;
- int hppiStatus;
- unsigned int response;
-
- statePtr = (NetHppiState *) interPtr->interfaceData;
- response = statePtr->hppidReg->responseData;
- /*
- * Acknowledge the interrupts by setting(!) the interrupt bits in the
- * status registers.
- */
- statePtr->hppisReg->status = NET_HPPI_SRC_STATUS_INTR;
- statePtr->hppidReg->status = NET_HPPI_DST_STATUS_INTR;
- MASTER_LOCK(&interPtr->mutex);
- if (response == DEV_HPPI_INTR_MAGIC) {
- void (*cb)();
- if ((cb = statePtr->outputCallback) != NULL) {
- if (netHppiDebug) {
- printf ("Received a HPPI testing interrupt.\n");
- }
- statePtr->outputCallback = NULL;
- MASTER_UNLOCK (&interPtr->mutex);
- (cb)(statePtr->outputClientData, SUCCESS);
- MASTER_LOCK (&interPtr->mutex);
- } else {
- printf ("Received a HPPI testing interrupt with no callback.\n");
- }
- goto intrExit;
- }
- #ifndef CLEAN
- if (netHppiDebug) {
- printf("Received an HPPI interrupt.\n");
- }
- #endif
- xrbPtr = statePtr->nextToHostPtr;
- #ifndef CLEAN
- if (netHppiTrace) {
- NEXT_TRACE(statePtr, &tracePtr);
- tracePtr->event = INTERRUPT;
- Timer_GetCurrentTicks(&tracePtr->ticks);
- }
- if (netHppiDebug) {
- printf ("NetHppiIntr: xrbPtr = 0x%x\n", xrbPtr);
- }
- #endif
- processed = 0;
- while(xrbPtr->filled != 0) {
- /*
- * Compute the next xrb to the host.
- */
- if (xrbPtr == statePtr->lastToHostPtr) {
- nextXRBPtr = statePtr->firstToHostPtr;
- } else {
- nextXRBPtr = xrbPtr + 1;
- }
- #ifndef CLEAN
- if (netHppiDebug) {
- printf ("NetHppiIntr: xrbPtr = 0x%x\n", xrbPtr);
- }
- #endif
- if (xrbPtr->filled == DEV_HPPI_FILLED_CMD) {
- Dev_HppiCmdHdr* hdr;
- statePtr->nextToHostPtr = nextXRBPtr;
- #ifndef CLEAN
- if (netHppiDebug) {
- hdr = (Dev_HppiCmdHdr*)&(xrbPtr->request);
- printf ("NetHppiIntr: processing command 0x%x\n", hdr->opcode);
- }
- #endif
- /*
- * This could get complicated, and will always require callbacks
- * anyway, so just schedule callback to process the return. The
- * command will always have an xrbId and xrbBufId which identify
- * the originator of the command. Don't clear the filled field;
- * that will be done by the callback.
- */
- Proc_CallFunc (NetHppiCmdCallback, (ClientData)xrbPtr, 0);
- processed += 1;
- } else {
- hdrPtr = (NetUltraRequestHdr *) &xrbPtr->request;
- infoPtr = statePtr->tagToXRBInfo[(int)hdrPtr->infoPtr];
- statePtr->nextToHostPtr = nextXRBPtr;
- dmaPtr = &xrbPtr->dma;
- if (!(dmaPtr->cmd & NET_ULTRA_DMA_CMD_FROM_ADAPTER)) {
- printf("NetHppiIntr: cmd (0x%x) not from adapter?\n", dmaPtr->cmd);
- goto endLoop;
- }
- if ((dmaPtr->cmd & NET_ULTRA_DMA_CMD_MASK) != NET_ULTRA_DMA_CMD_XRB) {
- printf("NetHppiIntr: dmaPtr->cmd = 0x%x\n", dmaPtr->cmd);
- goto endLoop;
- }
- if (infoPtr->flags & NET_ULTRA_INFO_PENDING) {
- #ifndef CLEAN
- if (netHppiDebug) {
- printf("NetHppiIntr: processing 0x%x\n", infoPtr);
- }
- if (netHppiTrace) {
- NEXT_TRACE(statePtr, &tracePtr);
- tracePtr->event = PROCESS_XRB;
- tracePtr->index = xrbPtr - statePtr->firstToHostPtr;
- tracePtr->infoPtr = infoPtr;
- Timer_GetCurrentTicks(&tracePtr->ticks);
- }
- #endif
- infoPtr->xrbPtr = xrbPtr;
- /*
- * Mark the info as not pending.
- * Clearing the pending bit ensures
- * that this packet does not get processed twice, since the
- * master lock around the interface will get released before
- * calling the RPC system, so that the RPC system can
- * output a packet. Do not
- * clear the filled bit since we are using the contents of
- * the xrb and we don't want the adapter to overwrite it
- * yet.
- */
- infoPtr->flags &= ~NET_ULTRA_INFO_PENDING;
- if (infoPtr->doneProc != NILPROC) {
- (infoPtr->doneProc)(interPtr, infoPtr);
- }
- if (infoPtr->flags & NET_ULTRA_INFO_STD_BUFFER) {
- if (infoPtr->flags & NET_ULTRA_INFO_REMAP) {
- VmMach_DMAFree(hdrPtr->size,
- VME_TO_DVMA(hdrPtr->buffer, statePtr));
- buffer = infoPtr->buffer;
- } else {
- buffer = VME_TO_BUFFER(hdrPtr->buffer, statePtr);
- }
- List_InitElement((List_Links *) buffer);
- List_Insert((List_Links *) buffer,
- LIST_ATREAR(statePtr->freeBufferList));
- }
- List_Remove((List_Links *) infoPtr);
- List_Insert((List_Links *) infoPtr,
- LIST_ATREAR(statePtr->freeXRBInfoList));
- processed++;
- } else {
- #ifndef CLEAN
- if (netHppiTrace) {
- NEXT_TRACE(statePtr, &tracePtr);
- tracePtr->event = INFO_NOT_PENDING;
- tracePtr->index = xrbPtr - statePtr->firstToHostPtr;
- tracePtr->infoPtr = infoPtr;
- }
- #endif
- }
- }
- endLoop:
- xrbPtr->filled = 0;
- xrbPtr = nextXRBPtr;
- }
-
-
- /*
- * Check to see if the HPPI-D board has a message for us.
- */
- hppiStatus = statePtr->hppidReg->status;
- if ((hppiStatus & NET_HPPI_DST_STATUS_ALIVE_MASK) ==
- NET_HPPI_DST_STATUS_ERROR) {
- statePtr->flags |= NET_HPPI_STATE_DST_ERROR;
- Proc_CallFunc (NetHppiMsgCallback, (ClientData)interPtr, 0);
- } else if (!(hppiStatus & DEV_HPPI_OFIFO_EMPTY)) {
- Proc_CallFunc (NetHppiMsgCallback, (ClientData)interPtr, 0);
- }
-
- /*
- * Check to see if the HPPI-S board has an error message for us.
- */
- hppiStatus = statePtr->hppisReg->status;
- if ((hppiStatus & NET_HPPI_SRC_STATUS_ALIVE_MASK) ==
- NET_HPPI_SRC_STATUS_ERROR) {
- statePtr->flags |= NET_HPPI_STATE_SRC_ERROR;
- Proc_CallFunc (NetHppiMsgCallback, (ClientData)interPtr, 0);
- }
-
- #ifndef CLEAN
- if (processed == 0) {
- if (netHppiDebug) {
- printf("NetHppiIntr: didn't process any packets.\n");
- }
- }
- #endif
- intrExit:
- MASTER_UNLOCK(&interPtr->mutex);
-
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiSetupBoard
- *
- * Send a setup command to the HPPI-D board. This should only be done
- * immediately after code is downloaded and run on the HPPI-D board.
- *
- * Results:
- * SUCCESS if command went OK
- * various failure codes otherwise
- *
- * Side effects:
- * A setup command is sent to the adapter.
- *
- *----------------------------------------------------------------------
- */
- static
- ReturnStatus
- NetHppiSetupBoard (statePtr)
- NetHppiState *statePtr;
- {
- Dev_HppiSetup setupCmd;
- ReturnStatus status = SUCCESS;
-
- /*
- * set up the configuration registers appropriately, in case
- * they were cleared when the link board was reset.
- *
- */
- statePtr->hppisReg->config = NET_HPPI_SRC_CONFIG_VALUE;
- statePtr->hppidReg->config = NET_HPPI_DST_CONFIG_VALUE;
-
- setupCmd.hdr.opcode = DEV_HPPI_SETUP;
- setupCmd.hdr.magic = DEV_HPPI_DEST_MAGIC;
- setupCmd.reqBlockSize = sizeof (NetUltraXRB);
- setupCmd.queueAddress = (uint32)(statePtr->firstToHostVME);
- setupCmd.queueSize = NET_HPPI_NUM_TO_HOST;
- status = NetHppiSendCmd (statePtr, sizeof (setupCmd),
- (Address)&setupCmd, 0);
-
- return (status);
- }
-
- /*----------------------------------------------------------------------
- *
- * NetHppiRomCmd --
- *
- * Send a command to the ROM monitor of one of the boards. After
- * the command is sent, the routine busy-waits for a reply.
- *
- * Results:
- * SUCCESS if the command was sent OK.
- * DEV_TIMEOUT if the device didn't complete the command
- *
- * Side effects:
- * A command is sent to one of the HPPI boards.
- *
- *----------------------------------------------------------------------
- */
- static
- ReturnStatus
- NetHppiRomCmd (interPtr, cmdBufPtr, cmdBufSize, responsePtr, responseSizePtr,
- flags)
- Net_Interface *interPtr;
- int *cmdBufPtr;
- int cmdBufSize;
- int *responsePtr;
- int *responseSizePtr;
- int flags;
- {
- NetHppiState *statePtr = (NetHppiState *)interPtr->interfaceData;
- ReturnStatus status = SUCCESS;
- volatile uint32 *boardStatus;
- int which;
- int responseSize;
- int garbage;
- int excess = 0;
-
- if (netHppiDebug) {
- printf ("NetHppiRomCmd: starting cmd.\n");
- }
-
- if (flags & NET_HPPI_SRC_CMD) {
- if (!(statePtr->flags & NET_HPPI_STATE_SRC_EPROM)) {
- printf ("NetHppiRomCmd: SRC board not running EPROM code\n");
- return (FAILURE);
- }
- which = NET_HPPI_SRC_CMD;
- boardStatus = &(statePtr->hppisReg->status);
- } else {
- if (!(statePtr->flags & NET_HPPI_STATE_DST_EPROM)) {
- printf ("NetHppiRomCmd: DST board not running EPROM code\n");
- return (FAILURE);
- }
- which = 0;
- boardStatus = &(statePtr->hppidReg->status);
- }
-
- responseSize = 0;
- MASTER_LOCK (&interPtr->mutex);
-
- NetHppiCopyToFifo (cmdBufPtr, cmdBufSize, statePtr, which);
-
- WAIT_FOR_BIT_CLEAR (boardStatus, NET_HPPI_DELAY, DEV_HPPI_OFIFO_EMPTY);
-
- status = NetHppiCopyFromFifo (&responseSize, sizeof (responseSize),
- statePtr, which);
- if (status != SUCCESS) {
- printf ("NetHppiRomCmd: command timed out.\n");
- status = DEV_TIMEOUT;
- goto exit;
- }
- *(responsePtr++) = responseSize;
- responseSize -= 4;
- if (responseSize > (*responseSizePtr)) {
- excess = responseSize - *responseSizePtr;
- responseSize = *responseSizePtr;
- }
-
- status = NetHppiCopyFromFifo (responsePtr, responseSize, statePtr, which);
- while (excess > 0) {
- (void)NetHppiCopyFromFifo (&garbage, sizeof(garbage), statePtr, which);
- excess -= sizeof (garbage);
- }
-
- /*
- * Correct so the size includes the first (size) word
- */
- *responseSizePtr = responseSize + 4;
-
- exit:
- MASTER_UNLOCK (&interPtr->mutex);
-
- if (netHppiDebug) {
- printf ("NetHppiRomCmd: returning...\n");
- }
- return (status);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiIOControl --
- *
- * Handle ioctls for the HPPI boards.
- *
- * Results:
- * SUCCESS if the ioctl was performed successfully, a standard
- * Sprite error code otherwise.
- *
- * Side effects:
- * Commands may be sent to the adapter and/or the either HPPI board,
- * and the adapter state and board states may change.
- *
- *----------------------------------------------------------------------
- */
-
- /*ARGSUSED*/
- ReturnStatus
- NetHppiIOControl(interPtr, ioctlPtr, replyPtr)
- Net_Interface *interPtr; /* Interface on which to perform ioctl. */
- Fs_IOCParam *ioctlPtr; /* Standard I/O Control parameter block */
- Fs_IOReply *replyPtr; /* Size of outBuffer and returned signal */
- {
- ReturnStatus status = SUCCESS;
- int fmtStatus;
- int inSize;
- int outSize;
- NetHppiState *statePtr = (NetHppiState *) interPtr->interfaceData;
-
- if (netHppiDebug) {
- printf("NetHppiIOControl: command = 0x%x\n", ioctlPtr->command);
- }
- if ((ioctlPtr->command & ~0xffff) != IOC_HPPI) {
- return DEV_INVALID_ARG;
- }
- switch(ioctlPtr->command) {
- case IOC_HPPI_SET_FLAGS:
- case IOC_HPPI_RESET_FLAGS:
- case IOC_HPPI_GET_FLAGS:
- return GEN_NOT_IMPLEMENTED;
- break;
- case IOC_HPPI_DEBUG: {
- int value;
- outSize = sizeof(int);
- inSize = ioctlPtr->inBufSize;
- fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format, &outSize,
- (Address) &value);
- if (fmtStatus != 0) {
- printf("Format of IOC_HPPI_DEBUG parameter failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- netHppiDebug = value;
- break;
- }
-
- case IOC_HPPI_TRACE: {
- int value;
- outSize = sizeof(int);
- inSize = ioctlPtr->inBufSize;
- fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format, &outSize,
- (Address) &value);
- if (fmtStatus != 0) {
- printf("Format of IOC_HPPI_TRACE parameter failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- netHppiTrace = value;
- break;
- }
- case IOC_HPPI_RESET:
- Net_HppiReset(interPtr);
- break;
- case IOC_HPPI_HARD_RESET:
- Net_HppiHardReset(interPtr);
- break;
- #if 0
- case IOC_HPPI_SRC_RESET:
- break;
- case IOC_HPPI_DST_RESET:
- break;
- #endif
- case IOC_HPPI_START: {
- MASTER_LOCK(&interPtr->mutex);
- status = NetHppiStart(statePtr);
- MASTER_UNLOCK(&interPtr->mutex);
- break;
- }
- case IOC_HPPI_GET_ADAP_INFO:
- return GEN_NOT_IMPLEMENTED;
- break;
- case IOC_HPPI_DIAG:
- case IOC_HPPI_EXTENDED_DIAG:
- return GEN_NOT_IMPLEMENTED;
- break;
-
- case IOC_HPPI_WRITE_REG: {
- Dev_HppiRegCmd writeCmd;
-
- inSize = ioctlPtr->inBufSize;
- outSize = sizeof (writeCmd);
- fmtStatus = Fmt_Convert ("www", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format,
- &outSize, (Address)&writeCmd);
- if (fmtStatus != FMT_OK) {
- printf ("Format of HPPI_WRITE_REG parameter failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- if (writeCmd.board == DEV_HPPI_SRC_BOARD) {
- if (writeCmd.offset >= sizeof (NetHppiSrcReg)) {
- printf ("HPPI_WRITE_REG: bad SRC register offset 0x%x\n",
- writeCmd.offset);
- return GEN_INVALID_ARG;
- }
- status = Mach_Probe (sizeof (int), (char *)&(writeCmd.value),
- (char *)(statePtr->hppisReg) + writeCmd.offset);
- } else if (writeCmd.board == DEV_HPPI_DST_BOARD) {
- if (writeCmd.offset >= sizeof (NetHppiDestReg)) {
- printf ("HPPI_WRITE_REG: bad DST register offset 0x%x\n",
- writeCmd.offset);
- return GEN_INVALID_ARG;
- }
- status = Mach_Probe (sizeof (int), (char *)&(writeCmd.value),
- (char *)(statePtr->hppidReg) + writeCmd.offset);
- } else if (writeCmd.board == DEV_HPPI_IOP_BOARD) {
- if (writeCmd.offset >= sizeof (NetHppiIopReg)) {
- printf ("HPPI_WRITE_REG: bad IOP register offset 0x%x\n",
- writeCmd.offset);
- return GEN_INVALID_ARG;
- }
- status = Mach_Probe (sizeof (int), (char *)&(writeCmd.value),
- (char *)(statePtr->iopReg) + writeCmd.offset);
- } else {
- return GEN_INVALID_ARG;
- }
- break;
- }
-
- case IOC_HPPI_READ_REG: {
- Dev_HppiRegCmd readCmd;
- uint32 regValue;
-
- inSize = ioctlPtr->inBufSize;
- outSize = sizeof (readCmd);
- fmtStatus = Fmt_Convert ("www", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format,
- &outSize, (Address)&readCmd);
- if (fmtStatus != FMT_OK) {
- printf ("Format of HPPI_READ_REG parameter failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- if (readCmd.board == DEV_HPPI_SRC_BOARD) {
- if (readCmd.offset >= sizeof (NetHppiSrcReg)) {
- printf ("HPPI_READ_REG: bad SRC register offset 0x%x\n",
- readCmd.offset);
- return GEN_INVALID_ARG;
- }
- status = Mach_Probe (sizeof(int),(char *)(statePtr->hppisReg) +
- readCmd.offset, (char *)®Value);
- } else if (readCmd.board == DEV_HPPI_DST_BOARD) {
- if (readCmd.offset >= sizeof (NetHppiDestReg)) {
- printf ("HPPI_READ_REG: bad DST register offset 0x%x\n",
- readCmd.offset);
- return GEN_INVALID_ARG;
- }
- status = Mach_Probe (sizeof(int),(char *)(statePtr->hppidReg) +
- readCmd.offset, (char *)®Value);
- } else if (readCmd.board == DEV_HPPI_IOP_BOARD) {
- if (readCmd.offset >= sizeof (NetHppiIopReg)) {
- printf ("HPPI_READ_REG: bad IOP register offset 0x%x\n",
- readCmd.offset);
- return GEN_INVALID_ARG;
- }
- status = Mach_Probe (sizeof(int), (char *)(statePtr->iopReg) +
- readCmd.offset, (char *)®Value);
- } else {
- return GEN_INVALID_ARG;
- }
- readCmd.value = regValue;
-
- if (ioctlPtr->outBufSize < sizeof (readCmd)) {
- printf ("HPPI_READ_REG: return buffer too small\n");
- return GEN_INVALID_ARG;
- }
- inSize = outSize = sizeof (readCmd);
- fmtStatus = Fmt_Convert ("www", mach_Format, &inSize,
- (Address)&readCmd, ioctlPtr->format,
- &outSize, (Address)ioctlPtr->outBuffer);
- if (fmtStatus != FMT_OK) {
- printf ("Format of HPPI_READ_REG output failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- break;
- }
-
- case IOC_HPPI_GO: {
- Dev_HppiGo goCmd;
- int flags;
- Dev_HppiRomGo hppiCmd;
- Dev_HppiRomGoReply hppiReply;
- int replySize;
-
- inSize = ioctlPtr->inBufSize;
- outSize = sizeof (goCmd);
- fmtStatus = Fmt_Convert ("w2", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format,
- &outSize, (Address)&goCmd);
- if (fmtStatus != FMT_OK) {
- printf ("Format of HPPI GO parameter failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- /*
- * Format the GO command
- */
- hppiCmd.hdr.length = sizeof (hppiCmd);
- hppiCmd.hdr.commandId = DEV_HPPI_START_CODES;
- hppiCmd.hdr.callerPid = 0;
- hppiCmd.startAddress = goCmd.startAddress;
-
- if ((goCmd.board != DEV_HPPI_SRC_BOARD) &&
- (goCmd.board != DEV_HPPI_DST_BOARD)) {
- printf ("IOC_HPPI_GO: bad board id (0x%x)\n", goCmd.board);
- return GEN_INVALID_ARG;
- }
- flags = (goCmd.board == DEV_HPPI_SRC_BOARD) ? NET_HPPI_SRC_CMD : 0;
- replySize = sizeof (hppiReply);
- status = NetHppiRomCmd (interPtr, &hppiCmd, sizeof (hppiCmd),
- &hppiReply, &replySize, flags);
-
- if (status != SUCCESS) {
- printf ("IOC_HPPI_GO: couldn't start code (0x%x)\n", status);
- return FAILURE;
- }
- if ((hppiReply.hdr.responseId != DEV_HPPI_START_CODES) ||
- (hppiReply.hdr.status != 0) ||
- (hppiReply.startAddress != goCmd.startAddress)) {
- printf ("IOC_HPPI_GO: response was wrong (r%d s%d a0x%x)\n",
- hppiReply.hdr.responseId, hppiReply.hdr.status,
- hppiReply.startAddress);
- return FAILURE;
- }
- if (goCmd.board == DEV_HPPI_SRC_BOARD) {
- statePtr->flags &= ~NET_HPPI_STATE_SRC_EPROM;
- } else {
- statePtr->flags &= ~NET_HPPI_STATE_DST_EPROM;
- }
-
- if (!(statePtr->flags & (NET_HPPI_STATE_SRC_EPROM |
- NET_HPPI_STATE_DST_EPROM))) {
- statePtr->flags |= NET_HPPI_STATE_NORMAL;
- }
- break;
- }
-
- case IOC_HPPI_LOAD: {
- Dev_HppiLoadHdr loadCmdHdr;
- Dev_HppiRomWrite *loadPtr;
- Dev_HppiRomWriteReply reply;
- int replySize = sizeof (reply);
- int flags;
-
- inSize = ioctlPtr->inBufSize;
- outSize = sizeof (loadCmdHdr);
- fmtStatus = Fmt_Convert ("w3", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format,
- &outSize, (Address)&loadCmdHdr);
- if (fmtStatus != FMT_OK) {
- printf ("Format of IOC_HPPI_LOAD parameter failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- inSize = outSize = loadCmdHdr.size;
- if (inSize >= DEV_HPPI_MAX_ROM_CMD_SIZE) {
- printf ("IOC_HPPI_LOAD: load data too big (0x%x)\n", inSize);
- return GEN_INVALID_ARG;
- }
- loadPtr = (Dev_HppiRomWrite *)
- malloc (sizeof (Dev_HppiRomWrite) + loadCmdHdr.size);
- if (loadPtr == NULL) {
- printf ("IOC_HPPI_LOAD: unable to allocate space\n");
- return FAILURE;
- }
- fmtStatus = Fmt_Convert ("w*", ioctlPtr->format, &inSize,
- (char *)ioctlPtr->inBuffer + sizeof (loadCmdHdr),
- mach_Format, &outSize, (Address)(loadPtr->data));
- if (fmtStatus != FMT_OK) {
- printf ("Format of IOC_HPPI_LOAD data failed, 0x%x\n",
- fmtStatus);
- status = GEN_INVALID_ARG;
- goto exitLoad;
- }
- loadPtr->hdr.commandId = DEV_HPPI_PUT_MEMORY;
- loadPtr->hdr.length = (sizeof (Dev_HppiRomWrite) - sizeof (int)) +
- loadCmdHdr.size;
- loadPtr->hdr.callerPid = 0;
- loadPtr->writeAddress = loadCmdHdr.startAddress;
- loadPtr->writeWords = loadCmdHdr.size / sizeof(int);
- flags =
- (loadCmdHdr.board == DEV_HPPI_SRC_BOARD) ? NET_HPPI_SRC_CMD :0;
- status = NetHppiRomCmd (interPtr, loadPtr, loadPtr->hdr.length,
- &reply, &replySize, flags);
- if ((status == SUCCESS) && (
- (reply.hdr.responseId != DEV_HPPI_PUT_MEMORY) ||
- (reply.hdr.status != 0) ||
- (reply.wordsWritten != loadPtr->writeWords))) {
- printf ("IOC_HPPI_LOAD: load failed (0x%x words)\n",
- reply.wordsWritten);
- status = FAILURE;
- }
- exitLoad:
- free ((Address)loadPtr);
- break;
- }
-
- case IOC_HPPI_SRC_ROM_CMD:
- case IOC_HPPI_DST_ROM_CMD: {
- int *cmdBufPtr;
- static int replyBuf[NET_HPPI_ROM_MAX_REPLY];
- int replySize;
- int flags;
-
- inSize = ioctlPtr->inBufSize;
- cmdBufPtr = (int *)malloc (inSize);
- outSize = inSize;
- fmtStatus = Fmt_Convert ("w*", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format,
- &outSize, (Address)cmdBufPtr);
- if (fmtStatus != FMT_OK) {
- printf ("Format of HPPI ROM parameter failed, 0x%x\n",
- fmtStatus);
- status = GEN_INVALID_ARG;
- goto exitRomCmd;
- }
- flags = (ioctlPtr->command == IOC_HPPI_SRC_ROM_CMD) ?
- NET_HPPI_SRC_CMD : 0;
- status = NetHppiRomCmd (interPtr, cmdBufPtr, inSize, replyBuf,
- &replySize, flags);
- if (status == SUCCESS) {
- if (replySize > ioctlPtr->outBufSize) {
- printf ("IOC_HPPI_ROM_CMD: reply too long\n");
- goto exitRomCmd;
- }
- inSize = replySize;
- fmtStatus = Fmt_Convert("w*", mach_Format, &replySize,
- (Address) replyBuf,
- ioctlPtr->format, &outSize,
- ioctlPtr->outBuffer);
- if (fmtStatus != 0) {
- printf("Format of HPPI ROM response failed, 0x%x\n",
- fmtStatus);
- status = GEN_INVALID_ARG;
- }
- } else {
- printf ("IOC_HPPI_ROM_CMD: command failed 0x%x\n", status);
- }
- exitRomCmd:
- free ((Address)cmdBufPtr);
- break;
- }
- case IOC_HPPI_SETUP: {
- MASTER_LOCK (&interPtr->mutex);
- status = NetHppiSetupBoard (statePtr);
- MASTER_UNLOCK (&interPtr->mutex);
- break;
- }
-
- case IOC_HPPI_SEND_DGRAM: {
- Dev_UltraSendDgram dgram;
- int *tmpBuf = (int *)NIL;
- inSize = ioctlPtr->inBufSize;
- outSize = sizeof(dgram);
- fmtStatus = Fmt_Convert("{{b8}w{w2}w2b*}",
- ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format, &outSize,
- (Address) &dgram);
- if (fmtStatus != 0) {
- if (fmtStatus == FMT_INPUT_TOO_SMALL) {
- return GEN_INVALID_ARG;
- } else {
- printf("NetHppiIOControl: Fmt_Convert returned %d\n",
- fmtStatus);
- return FAILURE;
- }
- }
- if (dgram.useBuffer != TRUE) {
- int i;
- tmpBuf = (int *)malloc (dgram.size);
- for (i = 0; i < dgram.size/4; i++) {
- *(tmpBuf + i) = i;
- }
- }
- status = NetHppiSendDgram(interPtr, &dgram.address, dgram.count,
- dgram.size,
- (dgram.useBuffer == TRUE) ? (Address) dgram.buffer :
- (Address) tmpBuf, &dgram.time);
- free ((char *)tmpBuf);
- inSize = sizeof(dgram);
- outSize = ioctlPtr->outBufSize;
- fmtStatus = Fmt_Convert("{{b8}w{w2}w2b*}", mach_Format, &inSize,
- (Address) &dgram, ioctlPtr->format, &outSize,
- (Address) ioctlPtr->outBuffer);
- if (fmtStatus != 0) {
- if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
- return GEN_INVALID_ARG;
- } else {
- printf(
- "NetHppiIOControl: Fmt_Convert returned %d\n",
- fmtStatus);
- return FAILURE;
- }
- }
- break;
- }
-
- case IOC_HPPI_RECV_DGRAM: {
- if (statePtr->flags & NET_HPPI_STATE_SINK) {
- if (netHppiDebug) {
- printf ("NetHppiIOControl: already sinking dgrams.\n");
- }
- return FAILURE;
- }
- statePtr->flags |= NET_HPPI_STATE_SINK;
- statePtr->flags &= ~NET_HPPI_STATE_NORMAL;
- Proc_CallFunc (NetHppiRecvDgram, (ClientData)interPtr, 0);
- break;
- }
-
- case IOC_HPPI_ECHO: {
- Dev_UltraEcho echo;
- inSize = ioctlPtr->inBufSize;
- outSize = sizeof(echo);
- fmtStatus = Fmt_Convert("{w}", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format, &outSize,
- (Address) &echo);
- if (fmtStatus != 0) {
- if (fmtStatus == FMT_INPUT_TOO_SMALL) {
- return GEN_INVALID_ARG;
- } else {
- printf("NetHppiIOControl: Fmt_Convert returned %d\n",
- fmtStatus);
- return FAILURE;
- }
- }
- if (echo.echo == TRUE) {
- statePtr->flags |= NET_HPPI_STATE_ECHO;
- statePtr->flags &= ~NET_HPPI_STATE_NORMAL;
- } else {
- statePtr->flags &= ~NET_HPPI_STATE_ECHO;
- statePtr->flags |= NET_HPPI_STATE_NORMAL;
- }
- break;
- }
-
- case IOC_HPPI_SOURCE: {
- Dev_UltraSendDgram dgram;
- inSize = ioctlPtr->inBufSize;
- outSize = sizeof(dgram);
- fmtStatus = Fmt_Convert("{{b8}w{w2}w2b*}",
- ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format, &outSize,
- (Address) &dgram);
- if (fmtStatus != 0) {
- if (fmtStatus == FMT_INPUT_TOO_SMALL) {
- return GEN_INVALID_ARG;
- } else {
- printf("NetHppiIOControl: Fmt_Convert returned %d\n",
- fmtStatus);
- return FAILURE;
- }
- }
- status = NetHppiSource(interPtr, &dgram.address, dgram.count,
- dgram.size,
- (dgram.useBuffer == TRUE) ? (Address) dgram.buffer :
- (Address) NIL, &dgram.time);
- inSize = sizeof(dgram);
- outSize = ioctlPtr->outBufSize;
- fmtStatus = Fmt_Convert("{{b8}w{w2}w2b*}", mach_Format, &inSize,
- (Address) &dgram, ioctlPtr->format, &outSize,
- (Address) ioctlPtr->outBuffer);
- if (fmtStatus != 0) {
- if (fmtStatus == FMT_OUTPUT_TOO_SMALL) {
- return GEN_INVALID_ARG;
- } else {
- printf(
- "NetHppiIOControl: Fmt_Convert returned %d\n",
- fmtStatus);
- return FAILURE;
- }
- }
- break;
- }
-
- case IOC_HPPI_SINK: {
- Dev_UltraSink sink;
- int value;
- outSize = sizeof(int);
- inSize = ioctlPtr->inBufSize;
- fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format, &outSize,
- (Address) &value);
- if (fmtStatus != 0) {
- printf("Format of IOC_HPPI_SINK parameter failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- outSize = ioctlPtr->outBufSize;
- sink.packets = packetsSunk;
- Timer_SubtractTicks(sinkEndTime, sinkStartTime, &sink.time);
- Timer_TicksToTime(sink.time, &sink.time);
- inSize = sizeof(sink);
- fmtStatus = Fmt_Convert("w{w2}", mach_Format, &inSize,
- (Address) &sink, ioctlPtr->format, &outSize,
- ioctlPtr->outBuffer);
- if (fmtStatus != 0) {
- printf("Format of IOC_HPPI_SINK parameter failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- if (value > 0) {
- statePtr->flags |= NET_HPPI_STATE_SINK;
- statePtr->flags &= ~NET_HPPI_STATE_NORMAL;
- packetsSunk = 0;
- } else {
- statePtr->flags &= ~NET_HPPI_STATE_SINK;
- statePtr->flags |= NET_HPPI_STATE_NORMAL;
- }
- break;
- }
-
- case IOC_HPPI_ADDRESS: {
- /*
- * Set the adapter address. This is not the normal way to
- * do this (usually happens during route installation) but
- * it is useful for debugging.
- */
- Net_UltraAddress address;
- int group;
- int unit;
- inSize = ioctlPtr->inBufSize;
- outSize = sizeof(Net_UltraAddress);
- fmtStatus = Fmt_Convert("{b8}", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format, &outSize,
- (Address) &address);
- if (fmtStatus != 0) {
- if (fmtStatus == FMT_INPUT_TOO_SMALL) {
- return GEN_INVALID_ARG;
- } else {
- printf("NetUltraIOControl: Fmt_Convert returned %d\n",
- fmtStatus);
- return FAILURE;
- }
- }
- Net_UltraAddressGet(&address, &group, &unit);
- printf("Setting ultra address to %d/%d\n", group, unit);
- MASTER_LOCK(&interPtr->mutex);
- status = Net_SetAddress(NET_ADDRESS_ULTRA,
- (Address) &address,
- &interPtr->netAddress[NET_PROTO_RAW]);
- if (status != SUCCESS) {
- panic("NetHppiIOControl: Net_SetAddress failed\n");
- }
- MASTER_UNLOCK(&interPtr->mutex);
- break;
- }
-
- case IOC_HPPI_COLLECT_STATS: {
- int value;
- inSize = ioctlPtr->inBufSize;
- outSize = sizeof(int);
- fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format, &outSize,
- (Address) &value);
- if (fmtStatus != 0) {
- if (fmtStatus == FMT_INPUT_TOO_SMALL) {
- return GEN_INVALID_ARG;
- } else {
- printf("NetHppiIOControl: Fmt_Convert returned %d\n",
- fmtStatus);
- return FAILURE;
- }
- }
- if (value == TRUE) {
- statePtr->flags |= NET_HPPI_STATE_STATS;
- } else {
- statePtr->flags &= ~NET_HPPI_STATE_STATS;
- }
- break;
- }
- case IOC_HPPI_CLEAR_STATS: {
- bzero((char *) &statePtr->stats, sizeof(statePtr->stats));
- break;
- }
- case IOC_HPPI_GET_STATS: {
- outSize = ioctlPtr->outBufSize;
- inSize = sizeof(Dev_UltraStats);
- fmtStatus = Fmt_Convert("w*", mach_Format, &inSize,
- (Address) &statePtr->stats,
- ioctlPtr->format, &outSize,
- ioctlPtr->outBuffer);
- if (fmtStatus != 0) {
- printf("Format of IOC_HPPI_GET_STATS parameter failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- break;
- }
-
- case IOC_HPPI_SET_TSAP: {
- char newTsap[4];
-
- inSize = outSize = sizeof (int);
- fmtStatus = Fmt_Convert("bbbb", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format, &outSize,
- (Address)&newTsap);
- if (fmtStatus != FMT_OK) {
- printf("Format of HPPI_SET_TSAP parm failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- if (netHppiDebug) {
- printf ("NetHppiIOControl: setting TSAP to %02x%02x%02x%02x\n",
- (unsigned char)newTsap[0], (unsigned char)newTsap[1],
- (unsigned char)newTsap[2], (unsigned char)newTsap[3]);
- }
- bcopy (newTsap, statePtr->curTsap, sizeof (statePtr->curTsap));
- break;
- }
- case IOC_HPPI_SET_BOARD_FLAGS:
- case IOC_HPPI_SET_SRC_BOARD_FLAGS:
- case IOC_HPPI_SET_DST_BOARD_FLAGS: {
- Dev_HppiSetBoardFlags flagCmd;
- inSize = outSize = sizeof (int);
- fmtStatus = Fmt_Convert("w", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format, &outSize,
- (Address)&(flagCmd.flags));
- if (fmtStatus != FMT_OK) {
- printf("Format of HPPI_SET_BOARD_FLAGS parm failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- statePtr->boardFlags = flagCmd.flags;
- flagCmd.hdr.opcode = DEV_HPPI_SET_BOARD_FLAGS;
- if ((ioctlPtr->command == IOC_HPPI_SET_BOARD_FLAGS) ||
- (ioctlPtr->command == IOC_HPPI_SET_SRC_BOARD_FLAGS)) {
- status = NetHppiSendCmd (statePtr, sizeof (flagCmd),
- (Address)&flagCmd, NET_HPPI_SRC_CMD);
- if (status != SUCCESS) {
- printf ("HPPI_SET_BOARD_FLAGS: SRC cmd failed\n");
- return (status);
- }
- }
- if ((ioctlPtr->command == IOC_HPPI_SET_BOARD_FLAGS) ||
- (ioctlPtr->command == IOC_HPPI_SET_DST_BOARD_FLAGS)) {
- status = NetHppiSendCmd (statePtr, sizeof (flagCmd),
- (Address)&flagCmd, 0);
- if (status != SUCCESS) {
- printf ("HPPI_SET_BOARD_FLAGS: DST cmd failed\n");
- return (status);
- }
- }
- break;
- }
-
- /*
- * NOTE: there is a memory leak in the following IOC call. This
- * call is to be used for testing purposes ONLY!
- */
- case IOC_HPPI_CONNECTION_OPEN: {
- Net_HppiConnection* connPtr;
- Sync_Condition gotOpen;
-
- connPtr = (Net_HppiConnection*)malloc(sizeof (Net_HppiConnection));
- inSize = outSize = sizeof (Net_HppiConnection);
- fmtStatus = Fmt_Convert("w9", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format,
- &outSize, (Address)connPtr);
- if (fmtStatus != FMT_OK) {
- printf("Format HPPI_CONNECTION_OPEN failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- connPtr->userData = (ClientData)&gotOpen;
- connPtr->interPtr = interPtr;
- connPtr->callbackProc = iocConnCallback;
- status = Net_HppiConnectionOpen (connPtr);
- if (status != SUCCESS) {
- printf ("HPPI_CONNECTION_OPEN: couldn't open 0x%x\n",
- status);
- return (FAILURE);
- }
- if (netHppiDebug) {
- printf ("HPPI_CONNECTION_OPEN: waiting...\n");
- }
- MASTER_LOCK (&(interPtr->mutex));
- Sync_MasterWait(&gotOpen, &(interPtr->mutex), FALSE);
- MASTER_UNLOCK (&(interPtr->mutex));
- if (netHppiDebug) {
- printf ("HPPI_CONNECTION_OPEN: returned from wait.\n");
- }
- connPtr->userData = (ClientData)connPtr;
- inSize = outSize = sizeof (Net_HppiConnection);
- fmtStatus = Fmt_Convert("w9", mach_Format, &inSize,
- (Address)connPtr, ioctlPtr->format,
- &outSize, ioctlPtr->outBuffer);
- if (fmtStatus != FMT_OK) {
- printf("Return format HPPI_CONNECTION_OPEN failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- status = connPtr->status;
- break;
- }
-
- case IOC_HPPI_CONNECTION_LISTEN: {
- Net_HppiConnection conn, *connPtr;
- Sync_Condition gotListen;
-
- inSize = outSize = sizeof (Net_HppiConnection);
- fmtStatus = Fmt_Convert("w9", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format,
- &outSize, (Address)&conn);
- if (fmtStatus != FMT_OK) {
- printf("Return format HPPI_CONNECTION_LISTEN failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- connPtr = (Net_HppiConnection*)conn.userData;
- connPtr->callbackProc = iocConnCallback;
- connPtr->interPtr = interPtr;
- connPtr->userData = (ClientData)&gotListen;
- status = Net_HppiConnectionListen (connPtr);
- if (status != SUCCESS) {
- printf ("HPPI_CONNECTION_LISTEN: couldn't listen 0x%x\n",
- status);
- return (FAILURE);
- }
- if (netHppiDebug) {
- printf ("HPPI_CONNECTION_LISTEN: waiting...\n");
- }
- MASTER_LOCK (&(interPtr->mutex));
- Sync_MasterWait(&gotListen, &(interPtr->mutex), FALSE);
- MASTER_UNLOCK (&(interPtr->mutex));
- if (netHppiDebug) {
- printf ("HPPI_CONNECTION_LISTEN: returned from wait.\n");
- }
- conn.status = connPtr->status;
- inSize = outSize = sizeof (Net_HppiConnection);
- fmtStatus = Fmt_Convert("w9", mach_Format, &inSize,
- (Address)&conn, ioctlPtr->format,
- &outSize, ioctlPtr->outBuffer);
- if (fmtStatus != FMT_OK) {
- printf("Return format HPPI_CONNECTION_LISTEN failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- break;
- }
-
- case IOC_HPPI_CONNECTION_SEND:
- case IOC_HPPI_CONNECTION_RECV:
- {
- Net_HppiConnection conn, *connPtr;
- Net_HppiDataRequest dataReq;
- Sync_Condition dataDone;
-
- inSize = outSize = sizeof (Net_HppiConnection);
- fmtStatus = Fmt_Convert("w9", ioctlPtr->format, &inSize,
- ioctlPtr->inBuffer, mach_Format,
- &outSize, (Address)&conn);
- if (fmtStatus != FMT_OK) {
- printf("Return format HPPI_CONNECTION_xfer failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- connPtr = (Net_HppiConnection*)conn.userData;
- connPtr->interPtr = interPtr;
- dataReq.interPtr = interPtr;
- dataReq.connectionId = connPtr->connectionId;
- dataReq.userData = (ClientData)&dataDone;
- dataReq.callbackProc = iocXferCallback;
- dataReq.xferSize = 100;
- dataReq.xferOffset = 0;
- dataReq.sgSize = 1;
- dataReq.sg[0].addr = (Address)0xff905000;
- dataReq.sg[0].length = 100;
- if (ioctlPtr->command == IOC_HPPI_CONNECTION_SEND) {
- status = Net_HppiSendData (connPtr, &dataReq);
- } else {
- status = Net_HppiReceiveData (connPtr, &dataReq);
- }
- if (status != SUCCESS) {
- printf ("HPPI_CONNECTION_xfer: couldn't transfer 0x%x\n",
- status);
- return (FAILURE);
- }
- if (netHppiDebug) {
- printf ("HPPI_CONNECTION_xfer: waiting...\n");
- }
- MASTER_LOCK (&(interPtr->mutex));
- Sync_MasterWait(&dataDone, &(interPtr->mutex), FALSE);
- MASTER_UNLOCK (&(interPtr->mutex));
- if (netHppiDebug) {
- printf ("HPPI_CONNECTION_xfer: returned from wait.\n");
- }
- conn.status = connPtr->status;
- inSize = outSize = sizeof (Net_HppiConnection);
- fmtStatus = Fmt_Convert("w9", mach_Format, &inSize,
- (Address)&conn, ioctlPtr->format,
- &outSize, ioctlPtr->outBuffer);
- if (fmtStatus != FMT_OK) {
- printf("Return format HPPI_CONNECTION_xfer failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- status = dataReq.status;
- break;
- }
- case IOC_HPPI_IOP_OUTPUT: {
- int ioSize;
-
- inSize = outSize = sizeof (ioSize);
- fmtStatus = Fmt_Convert ("w", ioctlPtr->format, &inSize,
- (Address)ioctlPtr->inBuffer,
- mach_Format, &outSize, (Address)&ioSize);
- if (fmtStatus != FMT_OK) {
- printf("Format of IOC_HPPI_IOP_OUTPUT size failed, 0x%x\n",
- fmtStatus);
- return GEN_INVALID_ARG;
- }
- MASTER_LOCK (&interPtr->mutex);
- statePtr->flags |= NET_HPPI_STATE_IOP_OUTPUT_TEST;
- NetHppiLoopback (statePtr, ioSize, iopOutputCallback,
- (ClientData)statePtr, 0);
- Sync_MasterWait (&iopOutputDone, &(interPtr->mutex), TRUE);
- MASTER_UNLOCK (&interPtr->mutex);
- }
- default: {
- printf("NetHppiIOControl: unknown ioctl 0x%x\n",
- ioctlPtr->command);
- }
-
- }
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiSendReq --
- *
- * Queue up a request for the adapter board. If there isn't
- * any room in the queue then we block until there is.
- *
- * Results:
- * Standard Sprite return status.
- *
- * Side effects:
- * The adapter board is notified of the addition to the queue.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- NetHppiSendReq(statePtr, doneProc, data, rpc, scatterLength, scatterPtr,
- requestSize, requestPtr)
- NetHppiState *statePtr; /* State of the adapter. */
- void (*doneProc)(); /* Procedure to call when
- * XRB is done. */
- ClientData data; /* Data used by doneProc. */
- Boolean rpc; /* Is this an RPC packet? */
- int scatterLength; /* Size of scatter/gather array. */
- Net_ScatterGather *scatterPtr; /* The scatter/gather array. */
- int requestSize; /* Size of the request. */
- NetUltraRequest *requestPtr; /* Request to be sent. */
- {
- NetUltraXRB *xrbPtr;
- NetUltraRequestHdr *hdrPtr;
- NetUltraDMAInfo *dmaPtr;
- ReturnStatus status = SUCCESS;
- int signal;
- NetUltraXRBInfo *infoPtr;
- NetUltraTraceInfo *tracePtr;
- int size;
- int i;
- Dev_HppiScatterGather sgList;
- Dev_HppiOutput outputCommand;
-
- if (netHppiDebug) {
- printf("NetHppiSendReq: sending a request\n");
- }
- xrbPtr = statePtr->nextToAdapterPtr;
-
- #ifndef CLEAN
- if (netHppiTrace) {
- NEXT_TRACE (statePtr, &tracePtr);
- tracePtr->event = SEND_REQ;
- tracePtr->index = xrbPtr - statePtr->firstToAdapterPtr;
- Timer_GetCurrentTicks (&tracePtr->ticks);
- }
-
- #endif
-
- /*
- * For the HPPI boards, the next xrb should never be filled, but
- * we'll leave the code in case we can DMA request blocks to the
- * adapter in the future.
- */
- if (statePtr->nextToAdapterPtr->filled) {
- do {
- if (netHppiDebug) {
- printf("NetHppiSendReq: no XRB free, waiting\n");
- }
- statePtr->toAdapterAvail.waiting = TRUE;
- signal = Sync_SlowMasterWait(
- (unsigned int) &statePtr->toAdapterAvail,
- &statePtr->interPtr->mutex, TRUE);
- if (signal) {
- return GEN_ABORTED_BY_SIGNAL;
- }
- } while(statePtr->nextToAdapterPtr->filled);
- }
- xrbPtr = statePtr->nextToAdapterPtr;
- hdrPtr = (NetUltraRequestHdr *) requestPtr;
- infoPtr = (NetUltraXRBInfo *) List_First(statePtr->freeXRBInfoList);
- if ((List_Links *) infoPtr == statePtr->freeXRBInfoList) {
- panic("NetHppiSendReq: no available XRBInfo structures!");
- }
- List_Remove((List_Links *) infoPtr);
- List_Insert((List_Links *) infoPtr,
- LIST_ATFRONT(statePtr->pendingXRBInfoList));
- infoPtr->doneProc = doneProc;
- infoPtr->doneData = data;
- infoPtr->xrbPtr = xrbPtr;
- infoPtr->scatterPtr = scatterPtr;
- infoPtr->scatterLength = scatterLength;
- infoPtr->requestSize = requestSize;
- infoPtr->requestPtr = (union NetUltraRequest *) requestPtr;
- infoPtr->flags = NET_ULTRA_INFO_PENDING;
-
- #if 0
- hdrPtr->infoPtr = infoPtr;
- #else
- hdrPtr->infoPtr = (NetUltraXRBInfo *)infoPtr->requestTag;
- statePtr->tagToXRBInfo[infoPtr->requestTag] = infoPtr;
- #endif
- hdrPtr->status = 0;
- hdrPtr->reference = 0;
-
- if (scatterLength > 0) {
- Address buffer;
- List_Links *itemPtr;
- /*
- * If the buffer is not in DVMA space then get one that is.
- */
- if (! DVMA_ADDRESS(scatterPtr[0].bufAddr, statePtr)) {
- if (netHppiDebug) {
- printf("Data is not in DVMA space.\n");
- }
- while(List_IsEmpty(statePtr->freeBufferList)) {
- int signal;
- statePtr->bufferAvail.waiting = TRUE;
- signal = Sync_SlowMasterWait(
- (unsigned int) &statePtr->bufferAvail,
- &statePtr->interPtr->mutex, TRUE);
- if (signal) {
- status = GEN_ABORTED_BY_SIGNAL;
- goto exit;
- }
- }
- itemPtr = List_First(statePtr->freeBufferList);
- if (itemPtr == statePtr->freeBufferList) {
- panic("NetHppiSendReq: list screwup\n");
- }
- List_Remove(itemPtr);
- buffer = (Address) itemPtr;
- infoPtr->flags |= NET_ULTRA_INFO_STD_BUFFER;
- if (rpc) {
- int lastIndex;
- /*
- * This is a standard RPC packet with 4 parts --
- * packet header, RPC header, RPC params, and data.
- * Copy the first three into the DVMA buffer. If the data
- * is below a threshold then copy it also. Otherwise
- * map the data into DVMA space and remap the first three parts
- * so that they precede the data.
- */
- size = 0;
- lastIndex = scatterLength - 1;
- for (i = 0; i < scatterLength; i++) {
- size += scatterPtr[i].length;
- }
- Net_GatherCopy(scatterPtr, scatterLength, buffer);
- } else {
-
- if (netHppiDebug) {
- printf("Copying data into DVMA space.\n");
- }
- Net_GatherCopy(scatterPtr, 1, buffer);
- size = scatterPtr[0].length;
- }
- } else {
- /*
- * The data is already in DVMA space. It had better be contiguous!
- */
- if (netHppiDebug) {
- printf("Data is already in DVMA space.\n");
- }
- buffer = scatterPtr[0].bufAddr;
- size = scatterPtr[0].length;
- }
- if (! DVMA_ADDRESS(buffer, statePtr)) {
- buffer = BUFFER_TO_DVMA(buffer, statePtr);
- }
- hdrPtr->buffer = DVMA_TO_VME(buffer, statePtr);
- hdrPtr->size = size;
- sgList.size = 1;
- sgList.element[0].address = (uint32)DVMA_TO_VME(buffer, statePtr);
- sgList.element[0].size = size;
- } else {
- hdrPtr->size = 0;
- sgList.size = 0;
- }
-
- if ((statePtr->flags & NET_HPPI_STATE_STATS) &&
- (hdrPtr->cmd == NET_ULTRA_DGRAM_SEND_REQ)) {
- statePtr->stats.packetsSent += 1;
- statePtr->stats.bytesSent += hdrPtr->size;
- statePtr->stats.sentHistogram[hdrPtr->size >> 10] += 1;
- }
-
- dmaPtr = &xrbPtr->dma;
-
- if (hdrPtr->cmd == NET_ULTRA_DGRAM_SEND_REQ) {
- dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB_DATA;
- statePtr->numWritePending++;
- if (statePtr->numWritePending > statePtr->maxWritePending) {
- panic("NetHppiSendReq: too many writes.\n");
- }
- } else if (hdrPtr->cmd == NET_ULTRA_DGRAM_RECV_REQ) {
- dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB;
- statePtr->numReadPending++;
- if (statePtr->numReadPending > statePtr->maxReadPending) {
- panic("NetHppiSendReq: too many reads.\n");
- }
- } else {
- dmaPtr->cmd = NET_ULTRA_DMA_CMD_XRB;
- }
-
- #if 0
- bcopy((char *) requestPtr, (char *) &xrbPtr->request, requestSize);
- #endif
- /*
- * The channel-based adapters require the command to also be
- * stuffed into the transaction ID in the DMA word.
- */
- dmaPtr->id = hdrPtr->cmd;
- dmaPtr->reference = 0;
- dmaPtr->length = requestSize;
- sgList.tag = (int)hdrPtr->infoPtr;
- dmaPtr->infoPtr = hdrPtr->infoPtr;
- if (netHppiDebug) {
- printf ("NetHppiSendReq: tag is 0x%x\n", sgList.tag);
- }
- dmaPtr->offset = 0;
- /*
- * Set the filled field so the adapter will process the XRB.
- */
- xrbPtr->filled = 1;
- if (statePtr->nextToAdapterPtr == statePtr->lastToAdapterPtr) {
- statePtr->nextToAdapterPtr = statePtr->firstToAdapterPtr;
- } else {
- statePtr->nextToAdapterPtr++;
- }
-
- /*
- * Send the command to the adapter. First, send the scatter-gather
- * list to the destination board. Next, send the request to the
- * source board.
- */
- if (netHppiTrace) {
- sgList.hdr.opcode = DEV_HPPI_SCATTER_GATHER_TRACE;
- outputCommand.hdr.opcode = DEV_HPPI_OUTPUT_TRACE;
- } else {
- sgList.hdr.opcode = DEV_HPPI_SCATTER_GATHER;
- outputCommand.hdr.opcode = DEV_HPPI_OUTPUT;
- }
- outputCommand.hdr.magic = DEV_HPPI_SRC_MAGIC;
- outputCommand.fifoDataSize = dmaPtr->length + sizeof (*dmaPtr);
- outputCommand.iopDataSize = 0;
- outputCommand.hdr.magic = DEV_HPPI_SRC_MAGIC;
- if (netHppiDebug) {
- printf("NetHppiSendReq: xrbPtr = 0x%x, sending %d bytes\n", xrbPtr,
- outputCommand.fifoDataSize);
- }
- if (scatterLength > 0) {
- size = sizeof (sgList.hdr)+sizeof (sgList.size)+sizeof (sgList.tag) +
- sizeof (Dev_HppiScatterGatherElement) * sgList.size;
- sgList.hdr.magic = DEV_HPPI_DEST_MAGIC;
- NetHppiSendCmd (statePtr, size, (Address)&sgList, 0);
- }
-
- status = NetHppiSendCmd (statePtr, sizeof (outputCommand),
- (Address)&outputCommand,
- NET_HPPI_KEEP_SRC_FIFO | NET_HPPI_SRC_CMD);
- if (status != SUCCESS) {
- goto exit;
- }
- status = NetHppiCopyToFifo (dmaPtr, sizeof (*dmaPtr), statePtr,
- NET_HPPI_SRC_CMD);
- if (status != SUCCESS) {
- goto exit;
- }
- status = NetHppiCopyToFifo (requestPtr, requestSize, statePtr,
- NET_HPPI_SRC_CMD);
- if (status != SUCCESS) {
- goto exit;
- }
- if (hdrPtr->cmd == NET_ULTRA_DGRAM_SEND_REQ) {
- outputCommand.fifoDataSize = hdrPtr->size;
- status = NetHppiSendCmd (statePtr, sizeof (outputCommand),
- (Address)&outputCommand,
- NET_HPPI_KEEP_SRC_FIFO | NET_HPPI_SRC_CMD);
- if (status != SUCCESS) {
- goto exit;
- }
- for (i = 0; i < sgList.size; i++) {
- status=NetHppiCopyToFifo (VME_TO_BUFFER(sgList.element[i].address,
- statePtr), sgList.element[i].size,
- statePtr, NET_HPPI_SRC_CMD);
- if (status != SUCCESS) {
- goto exit;
- }
- }
- }
-
- exit:
- /*
- * Since we just sent the XRB to the HPPI boards, it is no longer
- * filled. The code still acts like it is DMAed out (with filled
- * flags, etc.) so that it can be easily modified in the future if
- * the HPPI boards DMA requests out of memory at some future date.
- */
- xrbPtr->filled = 0;
- NetHppiReleaseSrcFifo (statePtr);
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * InitQueues --
- *
- * Initializes the XRB queues.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Memory is allocated and mapped into DMA space if necessary.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- InitQueues(statePtr)
- NetHppiState *statePtr; /* State of the adapter. */
- {
- int size;
- Address addr;
- List_Links *itemPtr;
- int i;
-
- if (!(statePtr->queuesInit)) {
- /*
- * Allocate XRBs that go from the adapter to the host.
- */
- size = sizeof(NetUltraXRB) * NET_HPPI_NUM_TO_HOST;
- #ifdef QUEUES_IN_DUALPORT_RAM
- statePtr->firstToHostVME = (Address)NET_HPPI_DUAL_PORT_RAM;
- statePtr->firstToAdapterVME = (Address) NET_HPPI_DUAL_PORT_RAM + size;
- addr = VmMach_MapInDevice (statePtr->firstToHostVME, 3);
- #else
- addr = (Address) malloc(size);
- addr = VmMach_DMAAlloc(size, (Address) addr);
- if (addr == (Address) NIL) {
- panic("NetUltraInit: unable to allocate DMA space.\n");
- }
- statePtr->firstToHostVME = DVMA_TO_VME (addr, statePtr);
- #endif
- statePtr->firstToHostPtr = (NetUltraXRB *) addr;
- /*
- * Allocate XRBs that go from the host to the adapter.
- */
- size = sizeof(NetUltraXRB) * NET_HPPI_NUM_TO_ADAPTER;
-
- #ifdef QUEUES_IN_DUALPORT_RAM
- addr = VmMach_MapInDevice (statePtr->firstToAdapterVME, 3);
- if (Mach_Probe (sizeof(int), addr + size, (Address)&i) == FAILURE) {
- panic ("NetHppiInit: circular queues too big.\n");
- }
- #else
- addr = (Address) malloc(size);
- addr = VmMach_DMAAlloc(size, (Address) addr);
- if (addr == (Address) NIL) {
- panic("NetUltraInit: unable to allocate DMA space.\n");
- }
- statePtr->firstToAdapterVME = DVMA_TO_VME (addr, statePtr);
- #endif
- statePtr->firstToAdapterPtr = (NetUltraXRB *) addr;
- statePtr->pendingXRBInfoList = &statePtr->pendingXRBInfoListHdr;
- statePtr->freeXRBInfoList = &statePtr->freeXRBInfoListHdr;
- List_Init(statePtr->pendingXRBInfoList);
- List_Init(statePtr->freeXRBInfoList);
- for (i = 0; i < NET_HPPI_NUM_TO_ADAPTER + NET_HPPI_NUM_TO_HOST; i++) {
- itemPtr = (List_Links *) malloc(sizeof(NetUltraXRBInfo));
- ((NetUltraXRBInfo *)itemPtr)->requestTag = i + 1;
- List_InitElement(itemPtr);
- List_Insert(itemPtr, LIST_ATREAR(statePtr->freeXRBInfoList));
- }
- /*
- * Allocate buffers in DVMA space for pending reads and writes.
- */
- statePtr->maxReadPending = NET_HPPI_PENDING_READS;
- statePtr->numReadPending = 0;
- statePtr->maxWritePending = NET_HPPI_PENDING_WRITES;
- statePtr->numWritePending = 0;
- statePtr->numBuffers = statePtr->maxReadPending +
- statePtr->maxWritePending;
- statePtr->bufferSize = NET_HPPI_MAX_BYTES;
- size = statePtr->numBuffers * statePtr->bufferSize;
- #if 1
- addr = (Address) malloc(size);
- statePtr->buffers = addr;
- addr = VmMach_DMAAlloc(size, (Address) addr);
- statePtr->buffersDVMA = addr;
- #else
- addr = NET_HPPI_DUAL_PORT_RAM + 0x4000;
- #endif
-
- statePtr->freeBufferList = &statePtr->freeBufferListHdr;
-
- statePtr->queuesInit = TRUE;
- }
- statePtr->lastToHostPtr = statePtr->firstToHostPtr +
- NET_HPPI_NUM_TO_HOST - 1;
- statePtr->nextToHostPtr = statePtr->firstToHostPtr;
- statePtr->lastToAdapterPtr = statePtr->firstToAdapterPtr +
- NET_HPPI_NUM_TO_ADAPTER - 1;
- statePtr->nextToAdapterPtr = statePtr->firstToAdapterPtr;
- size = sizeof(NetUltraXRB) * NET_HPPI_NUM_TO_HOST;
- bzero((char *) statePtr->firstToHostPtr, size);
- size = sizeof(NetUltraXRB) * NET_HPPI_NUM_TO_ADAPTER;
- bzero((char *) statePtr->firstToAdapterPtr, size);
- while (!List_IsEmpty(statePtr->pendingXRBInfoList)) {
- itemPtr = List_First(statePtr->pendingXRBInfoList);
- List_Remove(itemPtr);
- List_Insert(itemPtr, LIST_ATREAR(statePtr->freeXRBInfoList));
- }
- bzero((char *) statePtr->buffers, statePtr->numBuffers *
- statePtr->bufferSize);
- List_Init(statePtr->freeBufferList);
- for (i = 0; i < statePtr->numBuffers; i++) {
- itemPtr = (List_Links *)
- (statePtr->buffers + (i * statePtr->bufferSize));
- List_InitElement(itemPtr);
- List_Insert(itemPtr, LIST_ATREAR(statePtr->freeBufferList));
- }
- for (i = 0; i < NET_HPPI_MAX_TAGS; i++) {
- statePtr->tags[i] = 0;
- }
- statePtr->curSgTag = 1;
- for (i = 0; i < NET_HPPI_MAX_CONNECTIONS; i++) {
- statePtr->connection[i].flags = 0;
- statePtr->connection[i].statePtr = statePtr;
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiStart--
- *
- * Send a start request to the adapter.
- * Assumes the interface mutex is held.
- *
- * Results:
- * Standard Sprite return status.
- *
- * Side effects:
- * A start request is sent to the board.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- NetHppiStart(statePtr)
- NetHppiState *statePtr; /* State of the adapter. */
- {
- NetUltraRequest request;
- NetUltraStartRequest *startPtr;
- NetUltraRequestHdr *hdrPtr;
- Net_Interface *interPtr;
- int i;
- int power = 0;
- int tmp;
- ReturnStatus status = SUCCESS;
- static int sequence = 0;
- Sync_Condition startComplete;
-
- interPtr = statePtr->interPtr;
- startPtr = &request.start;
- hdrPtr = &startPtr->hdr;
- if (!Net_AddrCmp(&interPtr->netAddress[NET_PROTO_RAW], &netZeroAddress)) {
- printf("NetHppiStart: can't send start cmd-adapter address not set\n");
- status = FAILURE;
- goto exit;
- }
- if (statePtr->flags & NET_HPPI_STATE_START) {
- printf("NetHppiStart: adapter already started.\n");
- status = FAILURE;
- goto exit;
- } else if (statePtr->flags &
- (NET_HPPI_STATE_SRC_EPROM | NET_HPPI_STATE_DST_EPROM)) {
- printf ("NetHppiStart: boards not yet set up.\n");
- status = FAILURE;
- goto exit;
- }
- bzero((char *) &request, sizeof(request));
- hdrPtr->cmd = NET_ULTRA_NEW_START_REQ;
- startPtr->sequence = sequence;
- sequence++;
- startPtr->hostType = NET_ULTRA_START_HOSTTYPE_SUN;
- startPtr->adapterType = NET_ULTRA_START_ADAPTYPE_HSC;
- /*
- * Determine which power of 2 equals the maximum packet size.
- */
- tmp = interPtr->maxBytes;
- for (i = 0; i < sizeof(int) * 8; i++) {
- if (tmp & 1) {
- power = i;
- }
- tmp >>= 1;
- }
- if (1 << power > interPtr->maxBytes) {
- power++;
- }
- startPtr->hostMaxBytes = power;
- if (netHppiDebug) {
- printf ("NetHppiStart: power = %d\n", power);
- }
- /*
- * This part is kind of goofy. The adapter expects the network
- * address to be 7 bytes long (the first byte is missing). We have
- * to bcopy the netAddress minus its first byte.
- */
- startPtr->netAddressSize = 7;
- #if 0
- bcopy(&(((char *) &interPtr->netAddress[NET_PROTO_RAW])[1]),
- (char *) &startPtr->netAddressBuf, sizeof(Net_UltraAddress)-1);
- #endif
- bcopy ((char *)&(interPtr->netAddress[NET_PROTO_RAW].address.ultra) + 1,
- startPtr->netAddressBuf, startPtr->netAddressSize);
- startPtr->netAddressBuf[0] = 0x49;
- startPtr->netAddressBuf[5] = 0xfe;
- status = NetHppiSendReq(statePtr, StandardDone,
- (ClientData) &startComplete, FALSE,
- 0, (Net_ScatterGather *) NIL, sizeof(NetUltraStartRequest),
- &request);
- if (status != SUCCESS) {
- printf("NetHppiStart: unable to send start request\n");
- goto exit;
- }
- Sync_MasterWait(&(startComplete), &(interPtr->mutex), FALSE);
- if (netHppiDebug) {
- printf ("NetHppiStart: returned from wait\n");
- }
- if (hdrPtr->status & NET_ULTRA_STATUS_OK) {
- if (netHppiDebug) {
- printf("NetHppiStart: hdrPtr->status = %d : %s\n",
- hdrPtr->status, GetStatusString(hdrPtr->status));
- }
- if (netHppiDebug) {
- printf("Ultranet hub started\n");
- printf("Ucode %d\n", startPtr->ucodeRel);
- printf("Adapter type %d, adapter hw %d\n", startPtr->adapterType,
- startPtr->adapterHW);
- printf("Max VC = %d\n", startPtr->maxVC);
- printf("Max DRCV = %d\n", startPtr->maxDRCV);
- printf("Max DSND = %d\n", startPtr->maxDSND);
- printf("Slot = %d\n", startPtr->slot);
- printf("Speed = %d\n", startPtr->speed);
- printf("Max bytes = %d\n", (1 << startPtr->adapterMaxBytes));
- }
- if (startPtr->maxDRCV < statePtr->maxReadPending) {
- printf("NetHppiStart: WARNING: max pending reads reset to %d\n",
- startPtr->maxDRCV);
- statePtr->maxReadPending = startPtr->maxDRCV;
- }
- if (startPtr->maxDSND < statePtr->maxWritePending) {
- printf("NetUltraStart: WARNING: max pending writes reset to %d\n",
- startPtr->maxDSND);
- statePtr->maxWritePending = startPtr->maxDSND;
- }
- if (startPtr->adapterMaxBytes < power) {
- interPtr->maxBytes = 1 << power;
- printf("NetUltraStart: WARNING: max bytes reset to %d\n",
- interPtr->maxBytes);
- }
- statePtr->maxBytesPower = startPtr->adapterMaxBytes;
- statePtr->flags |= NET_HPPI_STATE_START;
- } else {
- printf("NetHppiStart: start command failed <0x%x> : %s\n",
- hdrPtr->status, GetStatusString(hdrPtr->status));
- }
-
- exit:
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiStop--
- *
- * Send a stop request to the board.
- * Assumes the interface mutex is held.
- *
- * Results:
- * Standard Sprite return status.
- *
- * Side effects:
- * The adapter abandons what it is doing.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- NetHppiStop(statePtr)
- NetHppiState *statePtr; /* State of the adapter. */
- {
- NetUltraRequest request;
- NetUltraStopRequest *stopPtr;
- NetUltraRequestHdr *hdrPtr;
- Net_Interface *interPtr;
- ReturnStatus status = SUCCESS;
- Sync_Condition stopComplete;
-
- interPtr = statePtr->interPtr;
- stopPtr = &request.stop;
- hdrPtr = &stopPtr->hdr;
- if (!(statePtr->flags & NET_HPPI_STATE_START)) {
- printf("NetHppiStop: adapter not started.\n");
- status = FAILURE;
- goto exit;
- }
- bzero((char *) &request, sizeof(request));
- hdrPtr->cmd = NET_ULTRA_STOP_REQ;
- status = NetHppiSendReq(statePtr, StandardDone,
- (ClientData) &stopComplete, FALSE,
- 0, (Net_ScatterGather *) NIL, sizeof(NetUltraStopRequest),
- &request);
- if (status != SUCCESS) {
- printf("NetHppiStop: unable to send stop request\n");
- goto exit;
- }
- Sync_MasterWait(&(stopComplete), &(interPtr->mutex), FALSE);
- if (hdrPtr->status & NET_ULTRA_STATUS_OK) {
- if (netHppiDebug) {
- printf("NetHppiStop: hdrPtr->status = %d : %s\n",
- hdrPtr->status, GetStatusString(hdrPtr->status));
- }
- statePtr->flags &= ~NET_HPPI_STATE_START;
- } else {
- printf("NetHppiStop: stop command failed <0x%x> : %s\n",
- hdrPtr->status, GetStatusString(hdrPtr->status));
- }
- exit:
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiSendDgram --
- *
- * This routine will send a datagram to the specified host. It
- * is intended for debugging purposes.
- *
- * Results:
- * None.
- *
- * Side effects:
- * A write is queued to the adapter.
- *
- *----------------------------------------------------------------------
- */
-
- static ReturnStatus
- NetHppiSendDgram(interPtr, netAddressPtr, count, bufSize, buffer, timePtr)
- Net_Interface *interPtr; /* Interface to send on. */
- Net_Address *netAddressPtr; /* Host to send to. */
- int count; /* Number of times to send
- * datagram. */
- int bufSize; /* Size of data buffer. */
- Address buffer; /* Data to send. */
- Time *timePtr; /* Place to store total
- * time to send datagrams. */
- {
- NetHppiState *statePtr;
- ReturnStatus status;
- Timer_Ticks startTime;
- Timer_Ticks endTime;
- Dev_HppiSendDSND dgramCmd;
-
- MASTER_LOCK(&interPtr->mutex);
- if (netHppiDebug) {
- char address[100];
- (void) Net_AddrToString(netAddressPtr, address);
- printf("NetHppiSendDgram: sending %d bytes to %s\n", bufSize, address);
- }
- statePtr = (NetHppiState *) interPtr->interfaceData;
- if (!(statePtr->flags & NET_HPPI_STATE_START)) {
- printf("NetHppiSendDgram: adapter not started!\n");
- status = FAILURE;
- goto exit;
- }
- bzero((char *) &dgramCmd, sizeof(dgramCmd));
- dgramCmd.hdr.opcode = DEV_HPPI_SEND_DSND;
- dgramCmd.xrbHdr.xrbId = (uint32)interPtr;
- dgramCmd.xrbHdr.xrbBufId = (uint32)&dgramCmd;
- bcopy ((char*)&(netAddressPtr->address.ultra)+1, &(dgramCmd.xrbRemTA),
- sizeof (dgramCmd.xrbRemTA));
- dgramCmd.xrbRemTA[0] = 0x49;
- dgramCmd.xrbRemTA[5] = 0xfe;
- bcopy ((char *)&(interPtr->netAddress[NET_PROTO_RAW].address.ultra) + 1,
- &(dgramCmd.xrbLocTA), sizeof (dgramCmd.xrbLocTA));
- dgramCmd.xrbLocTA[0] = 0x49;
- dgramCmd.xrbLocTA[5] = 0xfe;
- bcopy (statePtr->curTsap, dgramCmd.tsap, sizeof (dgramCmd.tsap));
-
- if (buffer == (Address)NIL) {
- buffer = statePtr->buffers;
- }
- dgramCmd.fifoDataSize = bufSize;
- dgramCmd.iopDataSize = 0;
- dgramCmd.xrbHdr.tag = 1;
- statePtr->flags |= NET_HPPI_STATE_DSND_TEST;
- statePtr->flags &= ~NET_HPPI_STATE_NORMAL;
- dsndCount = count;
- Timer_GetCurrentTicks(&startTime);
-
- status = NetHppiSendCmd (statePtr, sizeof (dgramCmd), (Address)&dgramCmd,
- NET_HPPI_SRC_CMD);
- if (status != SUCCESS) {
- if (netHppiDebug) {
- printf ("NetHppiSendDgram: command failed 0x%x\n", status);
- }
- goto exit;
- }
- status = NetHppiCopyToFifo (buffer, bufSize, statePtr, NET_HPPI_SRC_CMD);
- if (status != SUCCESS) {
- if (netHppiDebug) {
- printf ("NetHppiSendDgram: data copy failed 0x%x\n", status);
- }
- goto exit;
- }
-
- if (netHppiDebug) {
- printf ("NetHppiSendDgram: waiting for dgram to return.\n");
- }
- Sync_MasterWait(&dsndTestDone, &(interPtr->mutex), FALSE);
- Timer_GetCurrentTicks(&endTime);
- #ifndef CLEAN
- if (netHppiDebug) {
- printf("NetHppiSendDgram: test done.\n");
- }
- #endif
- statePtr->flags &= ~NET_HPPI_STATE_DSND_TEST;
- statePtr->flags |= NET_HPPI_STATE_NORMAL;
- Timer_SubtractTicks(endTime, startTime, &endTime);
- Timer_TicksToTime(endTime, timePtr);
- exit:
- MASTER_UNLOCK(&interPtr->mutex);
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * DgramSendDone --
- *
- * Called by the interrupt handler when the datagram sent by
- * NetUltraSendDgram is actually sent.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The process waiting for the datagram to be sent is notified.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- DgramSendDone(dgramCmdPtr)
- Dev_HppiSendDSND* dgramCmdPtr;
- {
- if (!(dgramCmdPtr->xrbHdr.status & NET_ULTRA_STATUS_OK)) {
- printf ("DgramSendDone: dgram send failed 0x%x\n",
- dgramCmdPtr->xrbHdr.status);
- } else {
- #ifndef CLEAN
- if (netHppiDebug) {
- printf("DgramSendDone: datagram sent ok\n");
- }
- #endif
- }
-
- Sync_MasterBroadcast ((Sync_Condition *) &dsndTestDone);
-
- #ifndef CLEAN
- if (netHppiDebug) {
- printf("DgramSendDone: returning.\n");
- }
- #endif
-
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiRecvDgram --
- *
- * This routine will receive a datagram. The receive address is
- * ignored, as is the buffer address (the link board memory will
- * be used). This is intended for debugging purposes, and is pretty
- * slow.
- *
- * Results:
- * None.
- *
- * Side effects:
- * A read is queued to the adapter.
- *
- *----------------------------------------------------------------------
- */
-
- static
- void
- NetHppiRecvDgram(interPtr)
- Net_Interface *interPtr; /* Interface to send on. */
- {
- int bufSize; /* Size of data buffer. */
- Address buffer; /* Data to send. */
- NetHppiState *statePtr = (NetHppiState*)interPtr->interfaceData;
- ReturnStatus status = SUCCESS;
- Timer_Ticks startTime;
- Timer_Ticks endTime;
- Dev_HppiSendDRCV dgramCmd;
- Dev_HppiScatterGather sgCmd;
- int sgCmdSize;
-
- MASTER_LOCK(&interPtr->mutex);
- while ((statePtr->flags & NET_HPPI_STATE_SINK) && (status == SUCCESS)) {
- bufSize = 0x8000;
- buffer = (Address)NET_HPPI_DUAL_PORT_RAM + 0x8000;
- #if 0
- if (netHppiDebug) {
- char address[100];
- (void) Net_AddrToString(netAddressPtr, address);
- printf("NetHppiRecvDgram: receiving %d bytes\n", bufSize);
- }
- #endif
- statePtr = (NetHppiState *) interPtr->interfaceData;
- if (!(statePtr->flags & NET_HPPI_STATE_START)) {
- printf("NetHppiRecvDgram: adapter not started!\n");
- status = FAILURE;
- goto exit;
- }
- /*
- * Send the scatter-gather array. Use the link board memory to store
- * the return data.
- */
- sgCmd.size = 1;
- sgCmd.offset = 0;
- if ((sgCmd.tag = getSgTag (statePtr)) == -1) {
- printf ("NetHppiRecvDgram: couldn't get SG tag.\n");
- status = FAILURE;
- goto exit;
- }
- sgCmd.element[0].address = (uint32)buffer;
- sgCmd.element[0].size = (uint32)bufSize;
- sgCmd.hdr.opcode = DEV_HPPI_SCATTER_GATHER;
- sgCmdSize = (sizeof (sgCmd) - sizeof (sgCmd.element)) +
- (sgCmd.size * sizeof (sgCmd.element[0]));
- status = NetHppiSendCmd (statePtr, sgCmdSize, (Address)&sgCmd,
- NET_HPPI_DST_CMD);
- if (status != SUCCESS) {
- printf ("NetHppiDgramRecv: SG command failed 0x%x\n", status);
- goto exit;
- }
-
- bzero((char *) &dgramCmd, sizeof(dgramCmd));
- dgramCmd.hdr.opcode = DEV_HPPI_SEND_DRCV;
- dgramCmd.xrbHdr.xrbId = (uint32)interPtr;
- dgramCmd.xrbHdr.xrbBufId = (uint32)&dgramCmd;
- dgramCmd.xrbHdr.tag = sgCmd.tag;
- bzero (&dgramCmd.xrbRemTA, sizeof (dgramCmd.xrbRemTA));
- bzero (&dgramCmd.xrbLocTA, sizeof (dgramCmd.xrbLocTA));
- bcopy (statePtr->curTsap, dgramCmd.tsap, sizeof (dgramCmd.tsap));
- #if 0
- dgramCmd.xrbRemTA[1] = 0x49;
- dgramCmd.xrbRemTA[6] = 0xfe;
- dgramCmd.xrbLocTA[1] = 0x49;
- dgramCmd.xrbLocTA[6] = 0xfe;
- #endif
- dgramCmd.cnt = bufSize;
-
- if (buffer == (Address)NIL) {
- buffer = statePtr->buffers;
- }
- Timer_GetCurrentTicks(&startTime);
-
- status = NetHppiSendCmd (statePtr, sizeof (dgramCmd),
- (Address)&dgramCmd, NET_HPPI_SRC_CMD);
- if (status != SUCCESS) {
- if (netHppiDebug) {
- printf ("NetHppiRecvDgram: command failed 0x%x\n", status);
- }
- goto exit;
- }
-
- if (netHppiDebug) {
- printf ("NetHppiRecvDgram: waiting to receive dgram.\n");
- }
- Sync_MasterWait(&drcvTestDone, &(interPtr->mutex), FALSE);
- Timer_GetCurrentTicks(&endTime);
- #ifndef CLEAN
- if (netHppiDebug) {
- printf("NetHppiRecvDgram: test done.\n");
- }
- #endif
- Timer_SubtractTicks(endTime, startTime, &endTime);
- #if 0
- Timer_TicksToTime(endTime, timePtr);
- #endif
- exit:
- ;
- }
- statePtr->flags &= ~NET_HPPI_STATE_SINK;
- MASTER_UNLOCK(&interPtr->mutex);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * DgramRecvDone --
- *
- * Called by the interrupt handler when the datagram requested by
- * NetUltraRecvDgram is actually received.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The process waiting for the datagram to be received is notified.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- DgramRecvDone(dgramCmdPtr)
- Dev_HppiSendDRCV* dgramCmdPtr;
- {
- Net_Interface* interPtr;
- NetHppiState* statePtr;
-
- interPtr = (Net_Interface*)(dgramCmdPtr->xrbHdr.xrbId);
- statePtr = (NetHppiState*)(interPtr->interfaceData);
- if (!(dgramCmdPtr->xrbHdr.status & NET_ULTRA_STATUS_OK)) {
- printf ("DgramRecvDone: dgram recv failed (status=0x%x)\n",
- dgramCmdPtr->xrbHdr.status);
- printf ("DgramRecvDone: terminating datagram sinking...\n");
- MASTER_LOCK (&interPtr->mutex);
- statePtr->flags &= ~NET_HPPI_STATE_SINK;
- statePtr->flags |= NET_HPPI_STATE_NORMAL;
- MASTER_UNLOCK (&interPtr->mutex);
- } else {
- #ifndef CLEAN
- if (netHppiDebug) {
- printf("DgramRecvDone: got datagram of size 0x%x\n",
- dgramCmdPtr->cnt);
- }
- #endif
- }
-
- Sync_MasterBroadcast ((Sync_Condition *) &drcvTestDone);
-
- #ifndef CLEAN
- if (netHppiDebug) {
- printf("DgramRecvDone: returning.\n");
- }
- #endif
-
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiOutputStub --
- *
- * Return FAILURE -- the network shouldn't be trying to output
- * RPC packets.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- NetHppiOutputStub(interPtr, hdrPtr, scatterGatherPtr, scatterGatherLength,
- rpc, statusPtr)
- Net_Interface *interPtr; /* The interface to use. */
- Address hdrPtr; /* Packet header. */
- Net_ScatterGather *scatterGatherPtr; /* Scatter/gather elems.*/
- int scatterGatherLength; /* Number of elements in
- * scatter/gather list. */
- Boolean rpc; /* Is this an RPC packet? */
- ReturnStatus *statusPtr; /* Place to store status. */
- {
- printf ("NetHppiOutputStub: shouldn't call HPPI for normal output.\n");
- return FAILURE;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiSource --
- *
- * This routine will send a stream of datagrams to the specified host.
- *
- * Results:
- * None.
- *
- * Side effects:
- * A write is queued to the adapter.
- *
- *----------------------------------------------------------------------
- */
-
- static ReturnStatus
- NetHppiSource(interPtr, netAddressPtr, count, bufSize, buffer, timePtr)
- Net_Interface *interPtr; /* Interface to send on. */
- Net_Address *netAddressPtr; /* Host to send to. */
- int count; /* Number of times to send
- * datagram. */
- int bufSize; /* Size of data buffer. */
- Address buffer; /* Data to send. */
- Time *timePtr; /* Place to store total
- * time to send datagrams. */
- {
- NetHppiState *statePtr;
- NetUltraRequest request;
- NetUltraDatagramRequest *dgramReqPtr;
- NetUltraRequestHdr *hdrPtr;
- ReturnStatus status = SUCCESS;
- Address itemPtr;
- char *ptr;
- Timer_Ticks startTime;
- Timer_Ticks endTime;
- Timer_Ticks curTime;
- NetUltraTraceInfo *tracePtr;
- Net_ScatterGather scatter;
-
- MASTER_LOCK(&interPtr->mutex);
- #ifndef CLEAN
- if (netHppiDebug) {
- char address[100];
- (void) Net_AddrToString(netAddressPtr, address);
- printf("NetHppiSendDgram: sending to %s\n", address);
- }
- #endif
- statePtr = (NetHppiState *) interPtr->interfaceData;
- bzero((char *) &request, sizeof(request));
- dgramReqPtr = &request.dgram;
- hdrPtr = &dgramReqPtr->hdr;
- dgramReqPtr->remoteAddress = wildcardAddress;
- dgramReqPtr->remoteAddress.tsapSize = 2;
- dgramReqPtr->remoteAddress.tsap[1] = 1;
- dgramReqPtr->remoteAddress.address = netAddressPtr->address.ultra;
- ptr = (char *) &dgramReqPtr->remoteAddress.address;
- ptr[1] = 0x49;
- ptr[6] = 0xfe;
- dgramReqPtr->localAddress = wildcardAddress;
- dgramReqPtr->localAddress.tsapSize = 2;
- dgramReqPtr->localAddress.tsap[1] = 1;
- dgramReqPtr->localAddress.address =
- interPtr->netAddress[NET_PROTO_RAW].address.ultra;
- ptr = (char *) &dgramReqPtr->localAddress.address;
- ptr[1] = 0x49;
- ptr[6] = 0xfe;
- hdrPtr->cmd = NET_ULTRA_DGRAM_SEND_REQ;
- Timer_GetCurrentTicks(&startTime);
- while(count > 0) {
- count--;
- itemPtr = getFreeBuffer (statePtr);
- if (itemPtr == (Address)NIL) {
- status = GEN_ABORTED_BY_SIGNAL;
- goto exit;
- }
- if (buffer != (Address) NIL) {
- bcopy((char *) buffer, itemPtr, bufSize);
- }
- dsndCount = count;
- #ifndef CLEAN
- if (netHppiTrace) {
- NEXT_TRACE(statePtr, &tracePtr);
- tracePtr->event = DSND_STREAM;
- Timer_GetCurrentTicks(&curTime);
- tracePtr->ticks = curTime;
- }
- #endif
- scatter.bufAddr = BUFFER_TO_DVMA(itemPtr, statePtr);
- scatter.length = bufSize;
- status = NetHppiSendReq(statePtr, SourceDone,
- (ClientData) NIL, FALSE, 1, &scatter,
- sizeof(NetUltraDatagramRequest), &request);
- }
- Timer_GetCurrentTicks(&endTime);
- Timer_SubtractTicks(endTime, startTime, &endTime);
- Timer_TicksToTime(endTime, timePtr);
- exit:
- MASTER_UNLOCK(&interPtr->mutex);
- return status;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * SourceDone --
- *
- * This routine is called by the interrupt handler when a packet
- * sent by NetUltraSource completes.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The write buffer associated with the command is added to
- * the list of free write buffers.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- SourceDone(interPtr, infoPtr)
- Net_Interface *interPtr; /* Interface. */
- NetUltraXRBInfo *infoPtr; /* Info about XRB that completed. */
- {
- NetUltraRequestHdr *hdrPtr;
- NetHppiState *statePtr;
- List_Links *itemPtr;
-
- hdrPtr = &(infoPtr->xrbPtr->request.dgram.hdr);
-
- statePtr = (NetHppiState *) interPtr->interfaceData;
- if (!(hdrPtr->status & NET_ULTRA_STATUS_OK)) {
- panic("SourceDone: write failed 0x%x (continuable)\n", hdrPtr->status);
- } else {
- #ifndef CLEAN
- if (netHppiDebug) {
- printf("SourceDone: packet sent\n");
- }
- #endif
- statePtr->numWritePending--;
- if (statePtr->numWritePending < 0) {
- panic("SourceDone: number of pending writes < 0.\n");
- }
- /*
- * Free up the write buffer.
- */
- itemPtr = (List_Links *) VME_TO_BUFFER(hdrPtr->buffer,statePtr);
- List_Insert(itemPtr, LIST_ATREAR(statePtr->freeBufferList));
- if (statePtr->bufferAvail.waiting == TRUE) {
- Sync_Broadcast(&statePtr->bufferAvail);
- }
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * NetHppiGetStats --
- *
- * Return the statistics for the interface.
- *
- * Results:
- * A pointer to the statistics structure.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- ReturnStatus
- NetHppiGetStats(interPtr, statPtr)
- Net_Interface *interPtr; /* Current interface. */
- Net_Stats *statPtr; /* Statistics to return. */
- {
- NetHppiState *statePtr;
-
- statePtr = (NetHppiState *) interPtr->interfaceData;
- MASTER_LOCK(&interPtr->mutex);
- statPtr->hppi = statePtr->stats;
- MASTER_UNLOCK(&interPtr->mutex);
- return SUCCESS;
- }
-
-
- /*
- *----------------------------------------------------------------------
- *
- * GetStatusString --
- *
- * Returns a string corresponding to the given status (status
- * is a field in a NetUltraRequestHdr.
- *
- * Results:
- * Ptr to string describing the status.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- static char *
- GetStatusString(status)
- unsigned char status;
- {
- static char *statusMsg[] = {
- "Unknown", /* 0 */
- "OK", /* 1 */
- "FAIL: invalid request", /* 2 */
- "OK: EOM", /* 3 */
- "FAIL: no resources", /* 4 */
- "OK: decide", /* 5 */
- "FAIL: unknown reference", /* 6 */
- "OK: closed", /* 7 */
- "FAIL: buffer too small", /* 8 */
- "OK; withdrawn", /* 9 */
- "FAIL: buffer too large", /* 10 */
- "OK: reject connection", /* 11 */
- "FAIL: illegal request", /* 12 */
- "OK: connection request", /* 13 */
- "FAIL: REM abort", /* 14 */
- "OK: closing", /* 15 */
- "FAIL: LOC timeout", /* 16 */
- "OK: timed-out", /* 17 */
- "FAIL: unknown connection class", /* 18 */
- "OK: out of sequence", /* 19 */
- "FAIL: duplicate request", /* 20 */
- "Unknown", /* 21 */
- "FAIL: connection rejected", /* 22 */
- "Unknown", /* 23 */
- "FAIL: negotiation failed", /* 24 */
- "Unknown", /* 25 */
- "FAIL: illegal address", /* 26 */
- "Unknown", /* 27 */
- "FAIL: network error", /* 28 */
- "Unknown", /* 29 */
- "FAIL: protocol error", /* 30 */
- "Unknown", /* 31 */
- "FAIL: illegal RB length", /* 32 */
- "Unknown", /* 33 */
- "FAIL: unknown SAP id", /* 34 */
- "Unknown", /* 35 */
- "FAIL: zero RB id", /* 36 */
- "Unknown", /* 37 */
- "FAIL: adapter down", /* 38 */
- };
- static int numStatusMsg = sizeof(statusMsg) / sizeof(char *);
-
- if (status >= numStatusMsg) {
- return "Unknown";
- } else {
- return statusMsg[status];
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * StandardDone --
- *
- * This is a callback routine that is called from the interrupt
- * handler when "standard" commands complete. It copies the request
- * from the XRB in the queue to the request structure pointed
- * to by the XRB. This allows the XRB to be used again.
- * If the data field in the info structure is not NIL then it
- * is assumed to be a pointer to a condition variable and a
- * broadcast is done on that variable.
- *
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *
- *----------------------------------------------------------------------
- */
-
- /* ARGSUSED */
- static void
- StandardDone(interPtr, infoPtr)
- Net_Interface *interPtr; /* Interface. */
- NetUltraXRBInfo *infoPtr; /* Info about XRB that completed. */
- {
- bcopy((char *) &infoPtr->xrbPtr->request, (char *) infoPtr->requestPtr,
- infoPtr->requestSize);
- if (infoPtr->doneData != (ClientData) NIL) {
- Sync_Broadcast((Sync_Condition *) infoPtr->doneData);
- }
- }
-
-
- /*----------------------------------------------------------------------
- *
- * setLocalAddress --
- *
- * Copy the current interface's network address into the passed
- * location.
- *
- * Results:
- * None.
- * Side effects:
- * Copies a network address.
- *
- *----------------------------------------------------------------------
- */
- static
- void
- setLocalAddress (interPtr, netAddrPtr)
- Net_Interface* interPtr;
- char* netAddrPtr;
- {
- bcopy ((char *)&(interPtr->netAddress[NET_PROTO_RAW].address.ultra) + 1,
- netAddrPtr, 7);
- netAddrPtr[0] = 0x49;
- netAddrPtr[5] = 0xfe;
-
- }
-
- /*----------------------------------------------------------------------
- *
- * NetHppiCmdCallback --
- *
- * This is the routine scheduled when a completed command is sent
- * into the ring buffer. It is called once for each command, and
- * is passed the address of the buffer to deal with. It simply
- * calls the appropriate handler for the type of message.
- *
- * Results:
- * none
- * Side effects:
- * none
- *
- *----------------------------------------------------------------------
- */
- void
- NetHppiCmdCallback (data, callInfoPtr)
- ClientData data;
- Proc_CallInfo* callInfoPtr;
- {
- Dev_HppiSendXfer* cmdPtr;
- NetUltraXRB* xrbPtr = (NetUltraXRB*)data;
- NetHppiConnState* connStatePtr;
-
- cmdPtr = (Dev_HppiSendXfer*)&(xrbPtr->request);
- if (cmdPtr->hdr.magic != DEV_HPPI_DEST_MAGIC) {
- panic ("NetHppiCmdCallback: bad magic number in command (0x%x)\n",
- cmdPtr->hdr.magic);
- }
- connStatePtr = (NetHppiConnState*)cmdPtr->xrbHdr.xrbId;
- switch (cmdPtr->hdr.opcode) {
- case DEV_HPPI_SEND_ALSN:
- NetHppiConnectionAccepted ((Dev_HppiSendALSN*)cmdPtr);
- break;
- case DEV_HPPI_SEND_OPEN:
- NetHppiOpenCallback ((Dev_HppiSendOPEN*)cmdPtr);
- break;
- case DEV_HPPI_SEND_CONN:
- break;
- case DEV_HPPI_SEND_CLSE:
- /*
- * The ISO reason code will be garbage, but the cleanup code
- * will ignore it in case of an abrupt (CLSE) close.
- */
- NetHppiConnectionCleanup ((Dev_HppiSendRLSE*)cmdPtr);
- break;
- case DEV_HPPI_SEND_RLSE:
- NetHppiConnectionCleanup ((Dev_HppiSendRLSE*)cmdPtr);
- break;
- case DEV_HPPI_SEND_SEND:
- case DEV_HPPI_SEND_SEOM:
- case DEV_HPPI_SEND_RECV:
- NetHppiXferCallback ((Dev_HppiSendXfer*)cmdPtr);
- break;
- case DEV_HPPI_SEND_DRCV:
- DgramRecvDone ((Dev_HppiSendDRCV*)cmdPtr);
- break;
- case DEV_HPPI_SEND_DSND:
- DgramSendDone ((Dev_HppiSendDSND*)cmdPtr);
- break;
- default:
- printf ("NetHppiCmdCallback: unknown command (0x%x)\n",
- cmdPtr->hdr.opcode);
- break;
- }
- /*
- * Now that we're done with the packet, we can declare it empty.
- */
- xrbPtr->filled = 0;
- }
-
-
- /*----------------------------------------------------------------------
- *
- * NetHppiOpenCallback --
- *
- * This procedure is called back when an open request returns.
- * It fills in the appropriate fields in the connection state
- * information, and then calls back the user-specified callback
- * routine.
- *
- * Returns:
- * none
- * Side effects:
- * Fills in connection state data structure.
- *
- *----------------------------------------------------------------------
- */
- void
- NetHppiOpenCallback (openBlockPtr)
- Dev_HppiSendOPEN* openBlockPtr;
- {
- Net_Interface* interPtr;
- NetHppiConnState* connStatePtr;
- Net_HppiConnection* connPtr;
- Boolean doCallback = TRUE;
-
- connStatePtr = (NetHppiConnState*)openBlockPtr->xrbHdr.xrbId;
- connPtr = (Net_HppiConnection*)openBlockPtr->xrbHdr.xrbBufId;
- interPtr = connPtr->interPtr;
- MASTER_LOCK (&interPtr->mutex);
- if (connStatePtr->flags & NET_HPPI_CONN_STATE_OPEN) {
- doCallback = FALSE;
- printf ("NetHppiOpenCallback: connection already open!\n");
- goto exit;
- } else if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_INUSE)) {
- doCallback = FALSE;
- printf ("NetHppiOpenCallback: connection not in use?!\n");
- goto exit;
- }
- if (openBlockPtr->xrbHdr.status != NET_ULTRA_STATUS_OK) {
- connStatePtr->flags &= ~NET_HPPI_CONN_STATE_INUSE;
- connPtr->status = NET_NOT_CONNECTED;
- } else {
- connStatePtr->flags |= NET_HPPI_CONN_STATE_OPEN;
- connStatePtr->xrbRef = openBlockPtr->xrbHdr.xrbRef;
- connPtr->status = SUCCESS;
- }
-
- exit:
- MASTER_UNLOCK (&interPtr->mutex);
- if (doCallback) {
- (*connPtr->callbackProc)(connPtr);
- }
- }
-
- /*----------------------------------------------------------------------
- *
- * Net_HppiConnectionOpen --
- *
- * Open a virtual circuit. This must be done before attempting
- * to listen on a virtual circuit. The calling semantics are
- * similar to Net_HppiConnectionListen.
- *
- * Returns:
- * Standard Sprite return status.
- * Side effects:
- * Sends a HPPI open request.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Net_HppiConnectionOpen (connStatusPtr)
- Net_HppiConnection* connStatusPtr;
- {
- ReturnStatus status = SUCCESS;
- NetHppiState* statePtr;
- NetHppiConnState* connStatePtr;
- Dev_HppiSendOPEN adapOpen;
- Net_Interface* interPtr;
- int connId;
-
- interPtr = connStatusPtr->interPtr;
- statePtr = (NetHppiState*)(interPtr->interfaceData);
- MASTER_LOCK (&interPtr->mutex);
-
- /*
- * Find a free connection ID.
- */
- for (connId = 0; connId < NET_HPPI_MAX_CONNECTIONS; connId += 1) {
- if (!(statePtr->connection[connId].flags & NET_HPPI_CONN_STATE_INUSE)){
- break;
- }
- }
- if (connId == NET_HPPI_MAX_CONNECTIONS) {
- printf ("Net_HppiConnectionListen: no connections available.\n");
- status = NET_NO_CONNECTS;
- goto exit;
- }
- connStatusPtr->connectionId = connId;
- connStatePtr = &(statePtr->connection[connId]);
- connStatePtr->userConnInfo = connStatusPtr;
- connStatePtr = &(statePtr->connection[connId]);
- connStatePtr->flags = NET_HPPI_CONN_STATE_INUSE;
- adapOpen.xrbHdr.xrbId = (uint32)connStatePtr;
- adapOpen.xrbHdr.xrbBufId = (uint32)connStatusPtr;
- adapOpen.xrbHdr.xrbRef = 0;
- adapOpen.xrbHdr.tag = 1;
- adapOpen.hdr.opcode = DEV_HPPI_SEND_OPEN;
- NetHppiSendCmd (statePtr, sizeof (adapOpen), (Address)&adapOpen,
- NET_HPPI_SRC_CMD);
- exit:
- MASTER_UNLOCK (&interPtr->mutex);
- return (status);
- }
-
- /*----------------------------------------------------------------------
- *
- * NetHppiConnectionAccepted --
- *
- * This is called via callback when a request block accepting a
- * connection comes in. Since it's always called via a Proc_Callfunc,
- * the connection callback is called directly at the end of the
- * routine.
- *
- * Results:
- * none
- * Side effects:
- * Calls a callback routine specified when the connection was requested.
- *
- *----------------------------------------------------------------------
- */
- void
- NetHppiConnectionAccepted (connBlockPtr)
- Dev_HppiSendALSN* connBlockPtr;
- {
- NetHppiState* statePtr;
- NetHppiConnState* connStatePtr;
- Net_HppiConnection* connPtr;
- Net_Interface* interPtr;
- Boolean doCallback = TRUE;
-
- connStatePtr = (NetHppiConnState*)connBlockPtr->xrbHdr.xrbId;
- connPtr = connStatePtr->userConnInfo;
- interPtr = connPtr->interPtr;
- statePtr = (NetHppiState*)interPtr->interfaceData;
-
- MASTER_LOCK (&interPtr->mutex);
- if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_LISTEN)) {
- MASTER_UNLOCK (&interPtr->mutex);
- printf ("NetHppiConnectionEstablish: connection %d not listening?\n",
- connPtr->connectionId);
- return;
- }
-
- if (connBlockPtr->xrbHdr.status == NET_HPPI_STATUS_CONN_REQ) {
- if (netHppiDebug) {
- printf ("NetHppiConnectionAccepted: connection requested.\n");
- }
- doCallback = FALSE;
- } else if (connBlockPtr->xrbHdr.status != NET_ULTRA_STATUS_OK) {
- if (netHppiDebug) {
- printf ("NetHppiConnectionAccepted: bad ultra status 0x%x\n",
- connBlockPtr->xrbHdr.status);
- }
- connStatePtr->flags &= ~NET_HPPI_CONN_STATE_INUSE;
- connPtr->status = NET_NOT_CONNECTED;
- } else {
- /*
- * Connection established, so set up shop.
- */
- connStatePtr->flags |= NET_HPPI_CONN_STATE_CONNECTED;
- connStatePtr->flags &= ~NET_HPPI_CONN_STATE_LISTEN;
- connStatePtr->numOutstandingRecv = 0;
- connStatePtr->numOutstandingSend = 0;
- List_Init (&connStatePtr->sendHdr);
- List_Init (&connStatePtr->recvHdr);
- connPtr->status = SUCCESS;
- }
- MASTER_UNLOCK (&interPtr->mutex);
- if (doCallback) {
- if (netHppiDebug) {
- printf ("NetHppiConnectionAccepted: doing user callback.\n");
- }
- (*connPtr->callbackProc)(connPtr);
- }
- }
-
- /*----------------------------------------------------------------------
- *
- * Net_HppiConnectionListen --
- *
- * Send an ALSN command to the HIPPI boards, and wait for a
- * connection request. When one is received, the callback
- * routine will be called.
- *
- * Results:
- * Standard Sprite return status.
- * Side effects:
- * Sends ALSN command to Ultra hub.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Net_HppiConnectionListen (connStatusPtr)
- Net_HppiConnection* connStatusPtr;
- {
- ReturnStatus status = SUCCESS;
- NetHppiState *statePtr;
- NetHppiConnState *connStatePtr;
- Dev_HppiSendALSN adapListen;
- Net_Interface* interPtr;
-
- interPtr = connStatusPtr->interPtr;
- statePtr = (NetHppiState*)(interPtr->interfaceData);
- connStatePtr = &(statePtr->connection[connStatusPtr->connectionId]);
- MASTER_LOCK (&interPtr->mutex);
- if (!(statePtr->flags & NET_HPPI_STATE_START)) {
- printf ("Net_HppiConnectionListen: adapter not started!\n");
- status = FAILURE;
- goto exit;
- }
- if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_OPEN)) {
- printf ("Net_HppiConnectionListen: channel not open!\n");
- status = FAILURE;
- goto exit;
- }
-
- if (netHppiDebug) {
- printf ("Net_HppiConnectionListen: using connection %d\n",
- connStatusPtr->connectionId);
- }
- connStatePtr->flags |= NET_HPPI_CONN_STATE_LISTEN;
- adapListen.xrbHdr.xrbRef = connStatePtr->xrbRef;
- adapListen.xrbHdr.xrbId = (uint32)connStatePtr;
- adapListen.xrbHdr.xrbBufId = (uint32)connStatusPtr;
- adapListen.xrbHdr.tag = 1;
- adapListen.hdr.opcode = DEV_HPPI_SEND_ALSN;
- bcopy (&netHppiConnPar,&adapListen.xrbConPar,sizeof(adapListen.xrbConPar));
- adapListen.xrbConPar[1] = statePtr->maxBytesPower;
- /*
- * Set remote address to wildcard. Set local to our address.
- */
- bzero (&adapListen.xrbRemTA, sizeof (adapListen.xrbRemTA));
- setLocalAddress (interPtr, &(adapListen.xrbLocTA));
- bcopy (statePtr->curTsap, adapListen.tsap, sizeof (adapListen.tsap));
- NetHppiSendCmd (statePtr, sizeof (adapListen), (Address)&adapListen,
- NET_HPPI_SRC_CMD);
-
- exit:
- MASTER_UNLOCK (&interPtr->mutex);
- return status;
- }
-
- /*----------------------------------------------------------------------
- *
- * NetHppiConnectionCleanup --
- *
- * Tear down the state associated with a connection. This aborts
- * all outstanding requests and frees the connection to be reused.
- * It is called when a request block indicating a closed connection
- * is received. This could be the result of either end wanting
- * to close the connection.
- *
- * Results:
- * Standard Sprite return status.
- * Side effects:
- * Many callbacks are scheduled.
- *
- *----------------------------------------------------------------------
- */
- static
- void
- NetHppiConnectionCleanup (cmdPtr)
- Dev_HppiSendRLSE* cmdPtr;
- {
- NetHppiState* statePtr;
- NetHppiConnState* connStatePtr;
- Net_Interface* interPtr;
- Net_HppiConnection* connPtr;
- List_Links freeUpList;
- Net_HppiDataRequest* reqPtr;
-
- connStatePtr = (NetHppiConnState*)cmdPtr->xrbHdr.xrbId;
- connPtr = (Net_HppiConnection*)cmdPtr->xrbHdr.xrbBufId;
- statePtr = connStatePtr->statePtr;
- interPtr = statePtr->interPtr;
-
- /*
- * At this point, we can free up any remaining data requests,
- * as the connection has been officially closed.
- */
- List_Init (&freeUpList);
- MASTER_LOCK (&interPtr->mutex);
- List_ListInsert (&connStatePtr->recvHdr, LIST_ATFRONT (&freeUpList));
- List_ListInsert (&connStatePtr->sendHdr, LIST_ATFRONT (&freeUpList));
- /*
- * Now that we've pulled the lists off the state pointer, the connection
- * may be reused (even before we've made all the callbacks for the
- * old connection), so mark the connection as free.
- */
- connStatePtr->flags = 0;
- MASTER_UNLOCK (&interPtr->mutex);
-
- /*
- * Send a callback for each of the still-outstanding requests.
- */
- while (!List_IsEmpty (&freeUpList)) {
- reqPtr = (Net_HppiDataRequest*)List_First (&freeUpList);
- List_Remove ((List_Links*)reqPtr);
- freeSgTag (statePtr, reqPtr->status);
- reqPtr->status = GEN_ABORTED_BY_SIGNAL;
- (*reqPtr->callbackProc)(reqPtr);
- }
- /*
- * Callback to indicate that the connection has finished closing.
- */
- (*connPtr->callbackProc)(connPtr);
- }
-
- /*----------------------------------------------------------------------
- *
- * Net_HppiConnectionClose --
- *
- * Close a connection that was already open. This routine will
- * call the routine to actually send a close packet to the adapter.
- * The connection state won't be nuked until the close packet
- * successfully returns.
- *
- * Results:
- * Sprite return status.
- * Side effects:
- * A HIPPI connection is closed.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Net_HppiConnectionClose (connPtr)
- Net_HppiConnection* connPtr;
- {
- ReturnStatus status = SUCCESS;
- Dev_HppiSendRLSE rlseCmd;
- Net_Interface* interPtr;
- NetHppiState* statePtr;
- NetHppiConnState* connStatePtr;
-
- if ((connPtr->connectionId < 0) ||
- (connPtr->connectionId > NET_HPPI_MAX_CONNECTIONS)) {
- return (FAILURE);
- }
- interPtr = connPtr->interPtr;
- statePtr = (NetHppiState*)interPtr->interfaceData;
- connStatePtr = &(statePtr->connection[connPtr->connectionId]);
- MASTER_LOCK (&interPtr->mutex);
- if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_CONNECTED)) {
- if (netHppiDebug) {
- printf ("Net_HppiConnectionClose: connection %d not connected.\n",
- connPtr->connectionId);
- }
- status = NET_NOT_CONNECTED;
- goto exit;
- }
- connStatePtr->flags &= ~NET_HPPI_CONN_STATE_CONNECTED;
- rlseCmd.xrbHdr.xrbId = (uint32)connStatePtr;
- rlseCmd.xrbHdr.xrbBufId = (uint32)connPtr;
- rlseCmd.xrbHdr.xrbRef = connStatePtr->xrbRef;
- rlseCmd.xrbHdr.tag = 1;
- rlseCmd.hdr.opcode = DEV_HPPI_SEND_RLSE;
- status = NetHppiSendCmd (statePtr, sizeof (rlseCmd), (Address)&rlseCmd,
- NET_HPPI_SRC_CMD);
- exit:
- MASTER_UNLOCK (&interPtr->mutex);
- if (status != SUCCESS) {
- printf ("Net_HppiConnectionClose: couldn't send RLSE command.\n");
- }
-
- return status;
- }
-
- /*----------------------------------------------------------------------
- *
- * NetHppiXferCallback --
- *
- * The callback for data being sent or received. Translate the Ultra
- * status into some kind of return code, and fill in the field in
- * the transfer request block. Unhook the block from the connection
- * state, and then callback the upper-level routine.
- *
- *----------------------------------------------------------------------
- */
- void
- NetHppiXferCallback (cmdPtr)
- Dev_HppiSendXfer* cmdPtr;
- {
- Net_HppiDataRequest* dataReqPtr;
- NetHppiConnState* connStatePtr;
- NetHppiState* statePtr;
-
- dataReqPtr = (Net_HppiDataRequest*)cmdPtr->xrbHdr.xrbBufId;
- connStatePtr = (NetHppiConnState*)cmdPtr->xrbHdr.xrbId;
- statePtr = connStatePtr->statePtr;
- if (netHppiDebug) {
- printf ("NetHppiXferCallback: returning call for request at 0x%x\n",
- dataReqPtr);
- }
-
- MASTER_LOCK (&statePtr->interPtr->mutex);
- if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_CONNECTED)) {
- if (netHppiDebug) {
- printf ("NetHppiXferCallback: connection no longer valid.\n");
- }
- MASTER_UNLOCK (&statePtr->interPtr->mutex);
- return;
- }
- freeSgTag (statePtr, dataReqPtr->status);
- if (cmdPtr->xrbHdr.status & NET_ULTRA_STATUS_OK) {
- dataReqPtr->status = SUCCESS;
- } else {
- if (netHppiDebug) {
- printf ("NetHppiXferCallback: got bad status 0x%x\n",
- cmdPtr->xrbHdr.status);
- }
- dataReqPtr->status = FAILURE;
- }
-
- List_Remove ((List_Links*)dataReqPtr);
- if (cmdPtr->hdr.opcode == DEV_HPPI_SEND_RECV) {
- connStatePtr->numOutstandingRecv -= 1;
- } else {
- connStatePtr->numOutstandingSend -= 1;
- }
- /*
- * Copy the actual transfer size back to the data request block.
- */
- dataReqPtr->xferSize = cmdPtr->cnt;
- MASTER_UNLOCK (&statePtr->interPtr->mutex);
-
- /*
- * Unmap buffers here if necessary (not yet implemented).
- */
- (*dataReqPtr->callbackProc)(dataReqPtr);
- }
-
- /*----------------------------------------------------------------------
- *
- * NetHppiXferData --
- *
- * Common code for sending or receiving data on an established
- * connection. The data is mapped into VME space if necessary.
- * Next, the appropriate scatter-gather array is sent to the
- * DST board. Finally, the request block is sent out to the
- * SRC board.
- *
- * Returns:
- * Standard Sprite return status.
- * Side effects:
- * none
- *
- *----------------------------------------------------------------------
- */
- static
- ReturnStatus
- NetHppiXferData (connPtr, dataReqPtr, which)
- Net_HppiConnection* connPtr; /* -> connection id block */
- Net_HppiDataRequest* dataReqPtr; /* -> data request */
- int which; /* send or receive? */
- {
- NetHppiState* statePtr;
- NetHppiConnState* connStatePtr;
- Dev_HppiSendXfer sendCmd;
- Dev_HppiScatterGather sgCmd;
- Net_Interface* interPtr = connPtr->interPtr;
- ReturnStatus status = SUCCESS;
- int sgCmdSize;
- int i;
-
- statePtr = (NetHppiState *)connPtr->interPtr->interfaceData;
- if ((connPtr->connectionId < 0) ||
- (connPtr->connectionId > NET_HPPI_MAX_CONNECTIONS)) {
- if (netHppiDebug) {
- printf ("NetHppiXferData: bad connection id (%d)\n",
- connPtr->connectionId);
- }
- return (FAILURE);
- }
- connStatePtr = &(statePtr->connection[connPtr->connectionId]);
-
- MASTER_LOCK (&interPtr->mutex);
- if (!(connStatePtr->flags & NET_HPPI_CONN_STATE_CONNECTED)) {
- status = NET_NOT_CONNECTED;
- goto exit;
- }
- /*
- * Set up the scatter-gather command. Map in buffers if necessary.
- */
- for (i = 0; i < dataReqPtr->sgSize; i++) {
- sgCmd.element[i].size = dataReqPtr->sg[i].length;
- /*
- * Must map buffer into VME if necessary. This isn't done yet.
- */
- sgCmd.element[i].address = (uint32)dataReqPtr->sg[i].addr;
- }
- sgCmd.size = dataReqPtr->sgSize;
- sgCmd.offset = dataReqPtr->xferOffset;
- sgCmd.hdr.opcode = DEV_HPPI_SCATTER_GATHER;
- sgCmdSize = sizeof (sgCmd) - sizeof (sgCmd.element) +
- (sgCmd.size * sizeof (sgCmd.element[0]));
-
- if ((sgCmd.tag = getSgTag (statePtr)) == -1) {
- status = FAILURE;
- goto exit;
- }
-
- dataReqPtr->status = sendCmd.xrbHdr.tag = sgCmd.tag;
- if (netHppiDebug) {
- printf ("NetHppiXferData: setting SG tag to %d\n", dataReqPtr->status);
- }
- /*
- * Add the request to the chain associated with the connection.
- */
- if (which == NET_HPPI_SEND) {
- if (connStatePtr->numOutstandingSend >= connPtr->outstandingSends) {
- status = GEN_ENOENT;
- goto exit;
- }
- connStatePtr->numOutstandingSend += 1;
- List_Insert ((List_Links *)dataReqPtr, &(connStatePtr->sendHdr));
- } else {
- if (connStatePtr->numOutstandingRecv >= connPtr->outstandingRecvs) {
- status = GEN_ENOENT;
- goto exit;
- }
- connStatePtr->numOutstandingRecv += 1;
- List_Insert ((List_Links *)dataReqPtr, &(connStatePtr->recvHdr));
- }
- /*
- * Send the scatter-gather command to the DST board.
- */
- status = NetHppiSendCmd (statePtr, sgCmdSize, (Address)&sgCmd,
- NET_HPPI_DST_CMD);
- if (status != SUCCESS) {
- goto exit;
- }
-
- /*
- * Build the data request command and send it to the SRC board.
- */
- sendCmd.xrbHdr.tag = sgCmd.tag;
- sendCmd.xrbHdr.xrbRef = connStatePtr->xrbRef;
- sendCmd.xrbHdr.xrbId = (uint32)connStatePtr;
- sendCmd.xrbHdr.xrbBufId = (uint32)dataReqPtr;
- sendCmd.cnt = dataReqPtr->xferSize;
- if (which == NET_HPPI_SEND) {
- sendCmd.hdr.opcode = DEV_HPPI_SEND_SEND;
- } else {
- sendCmd.hdr.opcode = DEV_HPPI_SEND_RECV;
- }
- status = NetHppiSendCmd (statePtr, sizeof (sendCmd), (Address)&sendCmd,
- NET_HPPI_SRC_CMD);
- exit:
- MASTER_UNLOCK (&interPtr->mutex);
- return status;
- }
-
- /*----------------------------------------------------------------------
- *
- * Net_HppiSendData --
- *
- * Send data over an established connection.
- *
- * Results:
- * Standard Sprite return status.
- * Side effects:
- * Data sent over the HIPPI boards.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Net_HppiSendData (connPtr, dataReqPtr)
- Net_HppiConnection* connPtr;
- Net_HppiDataRequest* dataReqPtr;
- {
- return (NetHppiXferData (connPtr, dataReqPtr, NET_HPPI_SEND));
- }
-
- /*----------------------------------------------------------------------
- *
- * Net_HppiReceiveData --
- *
- * Queue up a request to receive data over an established connection.
- * The callback routine will be called when all of the data is
- * received. The data must be contiguous within the connection (ie,
- * only one start offset and length), but may be placed according
- * to the request's scatter-gather array.
- *
- * Results:
- * Standard Sprite return status.
- * Side effects:
- * Requests that data be received.
- *
- *----------------------------------------------------------------------
- */
- ReturnStatus
- Net_HppiReceiveData (connPtr, dataReqPtr)
- Net_HppiConnection* connPtr;
- Net_HppiDataRequest* dataReqPtr;
- {
- return (NetHppiXferData (connPtr, dataReqPtr, NET_HPPI_RECV));
- }
-
- /*----------------------------------------------------------------------
- *
- * iocConnCallback
- *
- * Callback for the IOC connection call. This wakes up the waiting
- * IOC.
- *
- *----------------------------------------------------------------------
- */
- static
- void
- iocConnCallback (connPtr)
- Net_HppiConnection* connPtr;
- {
- Sync_Broadcast ((Sync_Condition *) connPtr->userData);
- }
-
- static
- void
- iocXferCallback (dataReqPtr)
- Net_HppiDataRequest* dataReqPtr;
- {
- Sync_Broadcast ((Sync_Condition *) dataReqPtr->userData);
- }
-